18732b070SChe-liang Chiou /*
28732b070SChe-liang Chiou * Copyright (c) 2013 The Chromium OS Authors.
3be6c1529SReinhard Pfau * Coypright (c) 2013 Guntermann & Drunck GmbH
48732b070SChe-liang Chiou *
51a459660SWolfgang Denk * SPDX-License-Identifier: GPL-2.0+
68732b070SChe-liang Chiou */
78732b070SChe-liang Chiou
88732b070SChe-liang Chiou #include <common.h>
9c8a8c510SSimon Glass #include <dm.h>
108732b070SChe-liang Chiou #include <tpm.h>
118732b070SChe-liang Chiou #include <asm/unaligned.h>
12c8a8c510SSimon Glass #include <u-boot/sha1.h>
138732b070SChe-liang Chiou
148732b070SChe-liang Chiou /* Internal error of TPM command library */
158732b070SChe-liang Chiou #define TPM_LIB_ERROR ((uint32_t)~0u)
168732b070SChe-liang Chiou
178732b070SChe-liang Chiou /* Useful constants */
188732b070SChe-liang Chiou enum {
198732b070SChe-liang Chiou COMMAND_BUFFER_SIZE = 256,
208732b070SChe-liang Chiou TPM_REQUEST_HEADER_LENGTH = 10,
218732b070SChe-liang Chiou TPM_RESPONSE_HEADER_LENGTH = 10,
228732b070SChe-liang Chiou PCR_DIGEST_LENGTH = 20,
23be6c1529SReinhard Pfau DIGEST_LENGTH = 20,
24be6c1529SReinhard Pfau TPM_REQUEST_AUTH_LENGTH = 45,
25be6c1529SReinhard Pfau TPM_RESPONSE_AUTH_LENGTH = 41,
26be6c1529SReinhard Pfau /* some max lengths, valid for RSA keys <= 2048 bits */
27be6c1529SReinhard Pfau TPM_KEY12_MAX_LENGTH = 618,
28be6c1529SReinhard Pfau TPM_PUBKEY_MAX_LENGTH = 288,
298732b070SChe-liang Chiou };
308732b070SChe-liang Chiou
31be6c1529SReinhard Pfau #ifdef CONFIG_TPM_AUTH_SESSIONS
32be6c1529SReinhard Pfau
33be6c1529SReinhard Pfau #ifndef CONFIG_SHA1
34be6c1529SReinhard Pfau #error "TPM_AUTH_SESSIONS require SHA1 to be configured, too"
35be6c1529SReinhard Pfau #endif /* !CONFIG_SHA1 */
36be6c1529SReinhard Pfau
37be6c1529SReinhard Pfau struct session_data {
38be6c1529SReinhard Pfau int valid;
39be6c1529SReinhard Pfau uint32_t handle;
40be6c1529SReinhard Pfau uint8_t nonce_even[DIGEST_LENGTH];
41be6c1529SReinhard Pfau uint8_t nonce_odd[DIGEST_LENGTH];
42be6c1529SReinhard Pfau };
43be6c1529SReinhard Pfau
44be6c1529SReinhard Pfau static struct session_data oiap_session = {0, };
45be6c1529SReinhard Pfau
46be6c1529SReinhard Pfau #endif /* CONFIG_TPM_AUTH_SESSIONS */
47be6c1529SReinhard Pfau
488732b070SChe-liang Chiou /**
498732b070SChe-liang Chiou * Pack data into a byte string. The data types are specified in
508732b070SChe-liang Chiou * the format string: 'b' means unsigned byte, 'w' unsigned word,
518732b070SChe-liang Chiou * 'd' unsigned double word, and 's' byte string. The data are a
528732b070SChe-liang Chiou * series of offsets and values (for type byte string there are also
538732b070SChe-liang Chiou * lengths). The data values are packed into the byte string
548732b070SChe-liang Chiou * sequentially, and so a latter value could over-write a former
558732b070SChe-liang Chiou * value.
568732b070SChe-liang Chiou *
578732b070SChe-liang Chiou * @param str output string
588732b070SChe-liang Chiou * @param size size of output string
598732b070SChe-liang Chiou * @param format format string
608732b070SChe-liang Chiou * @param ... data points
618732b070SChe-liang Chiou * @return 0 on success, non-0 on error
628732b070SChe-liang Chiou */
pack_byte_string(uint8_t * str,size_t size,const char * format,...)638732b070SChe-liang Chiou int pack_byte_string(uint8_t *str, size_t size, const char *format, ...)
648732b070SChe-liang Chiou {
658732b070SChe-liang Chiou va_list args;
668732b070SChe-liang Chiou size_t offset = 0, length = 0;
678732b070SChe-liang Chiou uint8_t *data = NULL;
688732b070SChe-liang Chiou uint32_t value = 0;
698732b070SChe-liang Chiou
708732b070SChe-liang Chiou va_start(args, format);
718732b070SChe-liang Chiou for (; *format; format++) {
728732b070SChe-liang Chiou switch (*format) {
738732b070SChe-liang Chiou case 'b':
748732b070SChe-liang Chiou offset = va_arg(args, size_t);
758732b070SChe-liang Chiou value = va_arg(args, int);
768732b070SChe-liang Chiou length = 1;
778732b070SChe-liang Chiou break;
788732b070SChe-liang Chiou case 'w':
798732b070SChe-liang Chiou offset = va_arg(args, size_t);
808732b070SChe-liang Chiou value = va_arg(args, int);
818732b070SChe-liang Chiou length = 2;
828732b070SChe-liang Chiou break;
838732b070SChe-liang Chiou case 'd':
848732b070SChe-liang Chiou offset = va_arg(args, size_t);
858732b070SChe-liang Chiou value = va_arg(args, uint32_t);
868732b070SChe-liang Chiou length = 4;
878732b070SChe-liang Chiou break;
888732b070SChe-liang Chiou case 's':
898732b070SChe-liang Chiou offset = va_arg(args, size_t);
908732b070SChe-liang Chiou data = va_arg(args, uint8_t *);
918732b070SChe-liang Chiou length = va_arg(args, uint32_t);
928732b070SChe-liang Chiou break;
938732b070SChe-liang Chiou default:
948732b070SChe-liang Chiou debug("Couldn't recognize format string\n");
958732b070SChe-liang Chiou return -1;
968732b070SChe-liang Chiou }
978732b070SChe-liang Chiou
9836d35345Sxypron.glpk@gmx.de if (offset + length > size) {
9936d35345Sxypron.glpk@gmx.de va_end(args);
1008732b070SChe-liang Chiou return -1;
10136d35345Sxypron.glpk@gmx.de }
1028732b070SChe-liang Chiou
1038732b070SChe-liang Chiou switch (*format) {
1048732b070SChe-liang Chiou case 'b':
1058732b070SChe-liang Chiou str[offset] = value;
1068732b070SChe-liang Chiou break;
1078732b070SChe-liang Chiou case 'w':
1088732b070SChe-liang Chiou put_unaligned_be16(value, str + offset);
1098732b070SChe-liang Chiou break;
1108732b070SChe-liang Chiou case 'd':
1118732b070SChe-liang Chiou put_unaligned_be32(value, str + offset);
1128732b070SChe-liang Chiou break;
1138732b070SChe-liang Chiou case 's':
1148732b070SChe-liang Chiou memcpy(str + offset, data, length);
1158732b070SChe-liang Chiou break;
1168732b070SChe-liang Chiou }
1178732b070SChe-liang Chiou }
1188732b070SChe-liang Chiou va_end(args);
1198732b070SChe-liang Chiou
1208732b070SChe-liang Chiou return 0;
1218732b070SChe-liang Chiou }
1228732b070SChe-liang Chiou
1238732b070SChe-liang Chiou /**
1248732b070SChe-liang Chiou * Unpack data from a byte string. The data types are specified in
1258732b070SChe-liang Chiou * the format string: 'b' means unsigned byte, 'w' unsigned word,
1268732b070SChe-liang Chiou * 'd' unsigned double word, and 's' byte string. The data are a
1278732b070SChe-liang Chiou * series of offsets and pointers (for type byte string there are also
1288732b070SChe-liang Chiou * lengths).
1298732b070SChe-liang Chiou *
1308732b070SChe-liang Chiou * @param str output string
1318732b070SChe-liang Chiou * @param size size of output string
1328732b070SChe-liang Chiou * @param format format string
1338732b070SChe-liang Chiou * @param ... data points
1348732b070SChe-liang Chiou * @return 0 on success, non-0 on error
1358732b070SChe-liang Chiou */
unpack_byte_string(const uint8_t * str,size_t size,const char * format,...)1368732b070SChe-liang Chiou int unpack_byte_string(const uint8_t *str, size_t size, const char *format, ...)
1378732b070SChe-liang Chiou {
1388732b070SChe-liang Chiou va_list args;
1398732b070SChe-liang Chiou size_t offset = 0, length = 0;
1408732b070SChe-liang Chiou uint8_t *ptr8 = NULL;
1418732b070SChe-liang Chiou uint16_t *ptr16 = NULL;
1428732b070SChe-liang Chiou uint32_t *ptr32 = NULL;
1438732b070SChe-liang Chiou
1448732b070SChe-liang Chiou va_start(args, format);
1458732b070SChe-liang Chiou for (; *format; format++) {
1468732b070SChe-liang Chiou switch (*format) {
1478732b070SChe-liang Chiou case 'b':
1488732b070SChe-liang Chiou offset = va_arg(args, size_t);
1498732b070SChe-liang Chiou ptr8 = va_arg(args, uint8_t *);
1508732b070SChe-liang Chiou length = 1;
1518732b070SChe-liang Chiou break;
1528732b070SChe-liang Chiou case 'w':
1538732b070SChe-liang Chiou offset = va_arg(args, size_t);
1548732b070SChe-liang Chiou ptr16 = va_arg(args, uint16_t *);
1558732b070SChe-liang Chiou length = 2;
1568732b070SChe-liang Chiou break;
1578732b070SChe-liang Chiou case 'd':
1588732b070SChe-liang Chiou offset = va_arg(args, size_t);
1598732b070SChe-liang Chiou ptr32 = va_arg(args, uint32_t *);
1608732b070SChe-liang Chiou length = 4;
1618732b070SChe-liang Chiou break;
1628732b070SChe-liang Chiou case 's':
1638732b070SChe-liang Chiou offset = va_arg(args, size_t);
1648732b070SChe-liang Chiou ptr8 = va_arg(args, uint8_t *);
1658732b070SChe-liang Chiou length = va_arg(args, uint32_t);
1668732b070SChe-liang Chiou break;
1678732b070SChe-liang Chiou default:
16836d35345Sxypron.glpk@gmx.de va_end(args);
1698732b070SChe-liang Chiou debug("Couldn't recognize format string\n");
1708732b070SChe-liang Chiou return -1;
1718732b070SChe-liang Chiou }
1728732b070SChe-liang Chiou
1738732b070SChe-liang Chiou if (offset + length > size)
1748732b070SChe-liang Chiou return -1;
1758732b070SChe-liang Chiou
1768732b070SChe-liang Chiou switch (*format) {
1778732b070SChe-liang Chiou case 'b':
1788732b070SChe-liang Chiou *ptr8 = str[offset];
1798732b070SChe-liang Chiou break;
1808732b070SChe-liang Chiou case 'w':
1818732b070SChe-liang Chiou *ptr16 = get_unaligned_be16(str + offset);
1828732b070SChe-liang Chiou break;
1838732b070SChe-liang Chiou case 'd':
1848732b070SChe-liang Chiou *ptr32 = get_unaligned_be32(str + offset);
1858732b070SChe-liang Chiou break;
1868732b070SChe-liang Chiou case 's':
1878732b070SChe-liang Chiou memcpy(ptr8, str + offset, length);
1888732b070SChe-liang Chiou break;
1898732b070SChe-liang Chiou }
1908732b070SChe-liang Chiou }
1918732b070SChe-liang Chiou va_end(args);
1928732b070SChe-liang Chiou
1938732b070SChe-liang Chiou return 0;
1948732b070SChe-liang Chiou }
1958732b070SChe-liang Chiou
1968732b070SChe-liang Chiou /**
1978732b070SChe-liang Chiou * Get TPM command size.
1988732b070SChe-liang Chiou *
1998732b070SChe-liang Chiou * @param command byte string of TPM command
2008732b070SChe-liang Chiou * @return command size of the TPM command
2018732b070SChe-liang Chiou */
tpm_command_size(const void * command)2028732b070SChe-liang Chiou static uint32_t tpm_command_size(const void *command)
2038732b070SChe-liang Chiou {
2048732b070SChe-liang Chiou const size_t command_size_offset = 2;
2058732b070SChe-liang Chiou return get_unaligned_be32(command + command_size_offset);
2068732b070SChe-liang Chiou }
2078732b070SChe-liang Chiou
2088732b070SChe-liang Chiou /**
2098732b070SChe-liang Chiou * Get TPM response return code, which is one of TPM_RESULT values.
2108732b070SChe-liang Chiou *
2118732b070SChe-liang Chiou * @param response byte string of TPM response
2128732b070SChe-liang Chiou * @return return code of the TPM response
2138732b070SChe-liang Chiou */
tpm_return_code(const void * response)2148732b070SChe-liang Chiou static uint32_t tpm_return_code(const void *response)
2158732b070SChe-liang Chiou {
2168732b070SChe-liang Chiou const size_t return_code_offset = 6;
2178732b070SChe-liang Chiou return get_unaligned_be32(response + return_code_offset);
2188732b070SChe-liang Chiou }
2198732b070SChe-liang Chiou
2208732b070SChe-liang Chiou /**
2218732b070SChe-liang Chiou * Send a TPM command and return response's return code, and optionally
2228732b070SChe-liang Chiou * return response to caller.
2238732b070SChe-liang Chiou *
2248732b070SChe-liang Chiou * @param command byte string of TPM command
2258732b070SChe-liang Chiou * @param response output buffer for TPM response, or NULL if the
2268732b070SChe-liang Chiou * caller does not care about it
2278732b070SChe-liang Chiou * @param size_ptr output buffer size (input parameter) and TPM
2288732b070SChe-liang Chiou * response length (output parameter); this parameter
2298732b070SChe-liang Chiou * is a bidirectional
2308732b070SChe-liang Chiou * @return return code of the TPM response
2318732b070SChe-liang Chiou */
tpm_sendrecv_command(const void * command,void * response,size_t * size_ptr)2328732b070SChe-liang Chiou static uint32_t tpm_sendrecv_command(const void *command,
2338732b070SChe-liang Chiou void *response, size_t *size_ptr)
2348732b070SChe-liang Chiou {
235c2b0f600SChristophe Ricard struct udevice *dev;
236667d6856STom Rini int err, ret;
2378732b070SChe-liang Chiou uint8_t response_buffer[COMMAND_BUFFER_SIZE];
2388732b070SChe-liang Chiou size_t response_length;
2398732b070SChe-liang Chiou
2408732b070SChe-liang Chiou if (response) {
2418732b070SChe-liang Chiou response_length = *size_ptr;
2428732b070SChe-liang Chiou } else {
2438732b070SChe-liang Chiou response = response_buffer;
2448732b070SChe-liang Chiou response_length = sizeof(response_buffer);
2458732b070SChe-liang Chiou }
246c8a8c510SSimon Glass
2473f603cbbSSimon Glass ret = uclass_first_device_err(UCLASS_TPM, &dev);
248c8a8c510SSimon Glass if (ret)
249c8a8c510SSimon Glass return ret;
250c8a8c510SSimon Glass err = tpm_xfer(dev, command, tpm_command_size(command),
251c8a8c510SSimon Glass response, &response_length);
252c2b0f600SChristophe Ricard
253c8a8c510SSimon Glass if (err < 0)
2548732b070SChe-liang Chiou return TPM_LIB_ERROR;
255be6c1529SReinhard Pfau if (size_ptr)
2568732b070SChe-liang Chiou *size_ptr = response_length;
2578732b070SChe-liang Chiou
2588732b070SChe-liang Chiou return tpm_return_code(response);
2598732b070SChe-liang Chiou }
2608732b070SChe-liang Chiou
tpm_init(void)261c8a8c510SSimon Glass int tpm_init(void)
2628732b070SChe-liang Chiou {
263c8a8c510SSimon Glass int err;
264c8a8c510SSimon Glass struct udevice *dev;
265c8a8c510SSimon Glass
2663f603cbbSSimon Glass err = uclass_first_device_err(UCLASS_TPM, &dev);
2673f603cbbSSimon Glass if (err)
268c8a8c510SSimon Glass return err;
269c8a8c510SSimon Glass return tpm_open(dev);
2708732b070SChe-liang Chiou }
2718732b070SChe-liang Chiou
tpm_startup(enum tpm_startup_type mode)2728732b070SChe-liang Chiou uint32_t tpm_startup(enum tpm_startup_type mode)
2738732b070SChe-liang Chiou {
2748732b070SChe-liang Chiou const uint8_t command[12] = {
2758732b070SChe-liang Chiou 0x0, 0xc1, 0x0, 0x0, 0x0, 0xc, 0x0, 0x0, 0x0, 0x99, 0x0, 0x0,
2768732b070SChe-liang Chiou };
2778732b070SChe-liang Chiou const size_t mode_offset = 10;
2788732b070SChe-liang Chiou uint8_t buf[COMMAND_BUFFER_SIZE];
2798732b070SChe-liang Chiou
2808732b070SChe-liang Chiou if (pack_byte_string(buf, sizeof(buf), "sw",
2818732b070SChe-liang Chiou 0, command, sizeof(command),
2828732b070SChe-liang Chiou mode_offset, mode))
2838732b070SChe-liang Chiou return TPM_LIB_ERROR;
2848732b070SChe-liang Chiou
2858732b070SChe-liang Chiou return tpm_sendrecv_command(buf, NULL, NULL);
2868732b070SChe-liang Chiou }
2878732b070SChe-liang Chiou
tpm_self_test_full(void)2888732b070SChe-liang Chiou uint32_t tpm_self_test_full(void)
2898732b070SChe-liang Chiou {
2908732b070SChe-liang Chiou const uint8_t command[10] = {
2918732b070SChe-liang Chiou 0x0, 0xc1, 0x0, 0x0, 0x0, 0xa, 0x0, 0x0, 0x0, 0x50,
2928732b070SChe-liang Chiou };
2938732b070SChe-liang Chiou return tpm_sendrecv_command(command, NULL, NULL);
2948732b070SChe-liang Chiou }
2958732b070SChe-liang Chiou
tpm_continue_self_test(void)2968732b070SChe-liang Chiou uint32_t tpm_continue_self_test(void)
2978732b070SChe-liang Chiou {
2988732b070SChe-liang Chiou const uint8_t command[10] = {
2998732b070SChe-liang Chiou 0x0, 0xc1, 0x0, 0x0, 0x0, 0xa, 0x0, 0x0, 0x0, 0x53,
3008732b070SChe-liang Chiou };
3018732b070SChe-liang Chiou return tpm_sendrecv_command(command, NULL, NULL);
3028732b070SChe-liang Chiou }
3038732b070SChe-liang Chiou
tpm_nv_define_space(uint32_t index,uint32_t perm,uint32_t size)3048732b070SChe-liang Chiou uint32_t tpm_nv_define_space(uint32_t index, uint32_t perm, uint32_t size)
3058732b070SChe-liang Chiou {
3068732b070SChe-liang Chiou const uint8_t command[101] = {
3078732b070SChe-liang Chiou 0x0, 0xc1, /* TPM_TAG */
3088732b070SChe-liang Chiou 0x0, 0x0, 0x0, 0x65, /* parameter size */
3098732b070SChe-liang Chiou 0x0, 0x0, 0x0, 0xcc, /* TPM_COMMAND_CODE */
3108732b070SChe-liang Chiou /* TPM_NV_DATA_PUBLIC->... */
3118732b070SChe-liang Chiou 0x0, 0x18, /* ...->TPM_STRUCTURE_TAG */
3128732b070SChe-liang Chiou 0, 0, 0, 0, /* ...->TPM_NV_INDEX */
3138732b070SChe-liang Chiou /* TPM_NV_DATA_PUBLIC->TPM_PCR_INFO_SHORT */
3148732b070SChe-liang Chiou 0x0, 0x3,
3158732b070SChe-liang Chiou 0, 0, 0,
3168732b070SChe-liang Chiou 0x1f,
3178732b070SChe-liang Chiou 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
3188732b070SChe-liang Chiou /* TPM_NV_DATA_PUBLIC->TPM_PCR_INFO_SHORT */
3198732b070SChe-liang Chiou 0x0, 0x3,
3208732b070SChe-liang Chiou 0, 0, 0,
3218732b070SChe-liang Chiou 0x1f,
3228732b070SChe-liang Chiou 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
3238732b070SChe-liang Chiou /* TPM_NV_ATTRIBUTES->... */
3248732b070SChe-liang Chiou 0x0, 0x17, /* ...->TPM_STRUCTURE_TAG */
3258732b070SChe-liang Chiou 0, 0, 0, 0, /* ...->attributes */
3268732b070SChe-liang Chiou /* End of TPM_NV_ATTRIBUTES */
3278732b070SChe-liang Chiou 0, /* bReadSTClear */
3288732b070SChe-liang Chiou 0, /* bWriteSTClear */
3298732b070SChe-liang Chiou 0, /* bWriteDefine */
3308732b070SChe-liang Chiou 0, 0, 0, 0, /* size */
3318732b070SChe-liang Chiou };
3328732b070SChe-liang Chiou const size_t index_offset = 12;
3338732b070SChe-liang Chiou const size_t perm_offset = 70;
3348732b070SChe-liang Chiou const size_t size_offset = 77;
3358732b070SChe-liang Chiou uint8_t buf[COMMAND_BUFFER_SIZE];
3368732b070SChe-liang Chiou
3378732b070SChe-liang Chiou if (pack_byte_string(buf, sizeof(buf), "sddd",
3388732b070SChe-liang Chiou 0, command, sizeof(command),
3398732b070SChe-liang Chiou index_offset, index,
3408732b070SChe-liang Chiou perm_offset, perm,
3418732b070SChe-liang Chiou size_offset, size))
3428732b070SChe-liang Chiou return TPM_LIB_ERROR;
3438732b070SChe-liang Chiou
3448732b070SChe-liang Chiou return tpm_sendrecv_command(buf, NULL, NULL);
3458732b070SChe-liang Chiou }
3468732b070SChe-liang Chiou
tpm_nv_read_value(uint32_t index,void * data,uint32_t count)3478732b070SChe-liang Chiou uint32_t tpm_nv_read_value(uint32_t index, void *data, uint32_t count)
3488732b070SChe-liang Chiou {
3498732b070SChe-liang Chiou const uint8_t command[22] = {
3508732b070SChe-liang Chiou 0x0, 0xc1, 0x0, 0x0, 0x0, 0x16, 0x0, 0x0, 0x0, 0xcf,
3518732b070SChe-liang Chiou };
3528732b070SChe-liang Chiou const size_t index_offset = 10;
3538732b070SChe-liang Chiou const size_t length_offset = 18;
3548732b070SChe-liang Chiou const size_t data_size_offset = 10;
3558732b070SChe-liang Chiou const size_t data_offset = 14;
3568732b070SChe-liang Chiou uint8_t buf[COMMAND_BUFFER_SIZE], response[COMMAND_BUFFER_SIZE];
3578732b070SChe-liang Chiou size_t response_length = sizeof(response);
3588732b070SChe-liang Chiou uint32_t data_size;
3598732b070SChe-liang Chiou uint32_t err;
3608732b070SChe-liang Chiou
3618732b070SChe-liang Chiou if (pack_byte_string(buf, sizeof(buf), "sdd",
3628732b070SChe-liang Chiou 0, command, sizeof(command),
3638732b070SChe-liang Chiou index_offset, index,
3648732b070SChe-liang Chiou length_offset, count))
3658732b070SChe-liang Chiou return TPM_LIB_ERROR;
3668732b070SChe-liang Chiou err = tpm_sendrecv_command(buf, response, &response_length);
3678732b070SChe-liang Chiou if (err)
3688732b070SChe-liang Chiou return err;
3698732b070SChe-liang Chiou if (unpack_byte_string(response, response_length, "d",
3708732b070SChe-liang Chiou data_size_offset, &data_size))
3718732b070SChe-liang Chiou return TPM_LIB_ERROR;
3728732b070SChe-liang Chiou if (data_size > count)
3738732b070SChe-liang Chiou return TPM_LIB_ERROR;
3748732b070SChe-liang Chiou if (unpack_byte_string(response, response_length, "s",
3758732b070SChe-liang Chiou data_offset, data, data_size))
3768732b070SChe-liang Chiou return TPM_LIB_ERROR;
3778732b070SChe-liang Chiou
3788732b070SChe-liang Chiou return 0;
3798732b070SChe-liang Chiou }
3808732b070SChe-liang Chiou
tpm_nv_write_value(uint32_t index,const void * data,uint32_t length)3818732b070SChe-liang Chiou uint32_t tpm_nv_write_value(uint32_t index, const void *data, uint32_t length)
3828732b070SChe-liang Chiou {
3838732b070SChe-liang Chiou const uint8_t command[256] = {
3848732b070SChe-liang Chiou 0x0, 0xc1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xcd,
3858732b070SChe-liang Chiou };
3868732b070SChe-liang Chiou const size_t command_size_offset = 2;
3878732b070SChe-liang Chiou const size_t index_offset = 10;
3888732b070SChe-liang Chiou const size_t length_offset = 18;
3898732b070SChe-liang Chiou const size_t data_offset = 22;
3908732b070SChe-liang Chiou const size_t write_info_size = 12;
3918732b070SChe-liang Chiou const uint32_t total_length =
3928732b070SChe-liang Chiou TPM_REQUEST_HEADER_LENGTH + write_info_size + length;
3938732b070SChe-liang Chiou uint8_t buf[COMMAND_BUFFER_SIZE], response[COMMAND_BUFFER_SIZE];
3948732b070SChe-liang Chiou size_t response_length = sizeof(response);
3958732b070SChe-liang Chiou uint32_t err;
3968732b070SChe-liang Chiou
3978732b070SChe-liang Chiou if (pack_byte_string(buf, sizeof(buf), "sddds",
3988732b070SChe-liang Chiou 0, command, sizeof(command),
3998732b070SChe-liang Chiou command_size_offset, total_length,
4008732b070SChe-liang Chiou index_offset, index,
4018732b070SChe-liang Chiou length_offset, length,
4028732b070SChe-liang Chiou data_offset, data, length))
4038732b070SChe-liang Chiou return TPM_LIB_ERROR;
4048732b070SChe-liang Chiou err = tpm_sendrecv_command(buf, response, &response_length);
4058732b070SChe-liang Chiou if (err)
4068732b070SChe-liang Chiou return err;
4078732b070SChe-liang Chiou
4088732b070SChe-liang Chiou return 0;
4098732b070SChe-liang Chiou }
4108732b070SChe-liang Chiou
tpm_extend(uint32_t index,const void * in_digest,void * out_digest)4118732b070SChe-liang Chiou uint32_t tpm_extend(uint32_t index, const void *in_digest, void *out_digest)
4128732b070SChe-liang Chiou {
4138732b070SChe-liang Chiou const uint8_t command[34] = {
4148732b070SChe-liang Chiou 0x0, 0xc1, 0x0, 0x0, 0x0, 0x22, 0x0, 0x0, 0x0, 0x14,
4158732b070SChe-liang Chiou };
4168732b070SChe-liang Chiou const size_t index_offset = 10;
4178732b070SChe-liang Chiou const size_t in_digest_offset = 14;
4188732b070SChe-liang Chiou const size_t out_digest_offset = 10;
4198732b070SChe-liang Chiou uint8_t buf[COMMAND_BUFFER_SIZE];
4208732b070SChe-liang Chiou uint8_t response[TPM_RESPONSE_HEADER_LENGTH + PCR_DIGEST_LENGTH];
4218732b070SChe-liang Chiou size_t response_length = sizeof(response);
4228732b070SChe-liang Chiou uint32_t err;
4238732b070SChe-liang Chiou
4248732b070SChe-liang Chiou if (pack_byte_string(buf, sizeof(buf), "sds",
4258732b070SChe-liang Chiou 0, command, sizeof(command),
4268732b070SChe-liang Chiou index_offset, index,
4278732b070SChe-liang Chiou in_digest_offset, in_digest,
4288732b070SChe-liang Chiou PCR_DIGEST_LENGTH))
4298732b070SChe-liang Chiou return TPM_LIB_ERROR;
4308732b070SChe-liang Chiou err = tpm_sendrecv_command(buf, response, &response_length);
4318732b070SChe-liang Chiou if (err)
4328732b070SChe-liang Chiou return err;
4338732b070SChe-liang Chiou
4348732b070SChe-liang Chiou if (unpack_byte_string(response, response_length, "s",
4358732b070SChe-liang Chiou out_digest_offset, out_digest,
4368732b070SChe-liang Chiou PCR_DIGEST_LENGTH))
4378732b070SChe-liang Chiou return TPM_LIB_ERROR;
4388732b070SChe-liang Chiou
4398732b070SChe-liang Chiou return 0;
4408732b070SChe-liang Chiou }
4418732b070SChe-liang Chiou
tpm_pcr_read(uint32_t index,void * data,size_t count)4428732b070SChe-liang Chiou uint32_t tpm_pcr_read(uint32_t index, void *data, size_t count)
4438732b070SChe-liang Chiou {
4448732b070SChe-liang Chiou const uint8_t command[14] = {
4458732b070SChe-liang Chiou 0x0, 0xc1, 0x0, 0x0, 0x0, 0xe, 0x0, 0x0, 0x0, 0x15,
4468732b070SChe-liang Chiou };
4478732b070SChe-liang Chiou const size_t index_offset = 10;
4488732b070SChe-liang Chiou const size_t out_digest_offset = 10;
4498732b070SChe-liang Chiou uint8_t buf[COMMAND_BUFFER_SIZE], response[COMMAND_BUFFER_SIZE];
4508732b070SChe-liang Chiou size_t response_length = sizeof(response);
4518732b070SChe-liang Chiou uint32_t err;
4528732b070SChe-liang Chiou
4538732b070SChe-liang Chiou if (count < PCR_DIGEST_LENGTH)
4548732b070SChe-liang Chiou return TPM_LIB_ERROR;
4558732b070SChe-liang Chiou
4568732b070SChe-liang Chiou if (pack_byte_string(buf, sizeof(buf), "sd",
4578732b070SChe-liang Chiou 0, command, sizeof(command),
4588732b070SChe-liang Chiou index_offset, index))
4598732b070SChe-liang Chiou return TPM_LIB_ERROR;
4608732b070SChe-liang Chiou err = tpm_sendrecv_command(buf, response, &response_length);
4618732b070SChe-liang Chiou if (err)
4628732b070SChe-liang Chiou return err;
4638732b070SChe-liang Chiou if (unpack_byte_string(response, response_length, "s",
4648732b070SChe-liang Chiou out_digest_offset, data, PCR_DIGEST_LENGTH))
4658732b070SChe-liang Chiou return TPM_LIB_ERROR;
4668732b070SChe-liang Chiou
4678732b070SChe-liang Chiou return 0;
4688732b070SChe-liang Chiou }
4698732b070SChe-liang Chiou
tpm_tsc_physical_presence(uint16_t presence)4708732b070SChe-liang Chiou uint32_t tpm_tsc_physical_presence(uint16_t presence)
4718732b070SChe-liang Chiou {
4728732b070SChe-liang Chiou const uint8_t command[12] = {
4738732b070SChe-liang Chiou 0x0, 0xc1, 0x0, 0x0, 0x0, 0xc, 0x40, 0x0, 0x0, 0xa, 0x0, 0x0,
4748732b070SChe-liang Chiou };
4758732b070SChe-liang Chiou const size_t presence_offset = 10;
4768732b070SChe-liang Chiou uint8_t buf[COMMAND_BUFFER_SIZE];
4778732b070SChe-liang Chiou
4788732b070SChe-liang Chiou if (pack_byte_string(buf, sizeof(buf), "sw",
4798732b070SChe-liang Chiou 0, command, sizeof(command),
4808732b070SChe-liang Chiou presence_offset, presence))
4818732b070SChe-liang Chiou return TPM_LIB_ERROR;
4828732b070SChe-liang Chiou
4838732b070SChe-liang Chiou return tpm_sendrecv_command(buf, NULL, NULL);
4848732b070SChe-liang Chiou }
4858732b070SChe-liang Chiou
tpm_read_pubek(void * data,size_t count)4868732b070SChe-liang Chiou uint32_t tpm_read_pubek(void *data, size_t count)
4878732b070SChe-liang Chiou {
4888732b070SChe-liang Chiou const uint8_t command[30] = {
4898732b070SChe-liang Chiou 0x0, 0xc1, 0x0, 0x0, 0x0, 0x1e, 0x0, 0x0, 0x0, 0x7c,
4908732b070SChe-liang Chiou };
4918732b070SChe-liang Chiou const size_t response_size_offset = 2;
4928732b070SChe-liang Chiou const size_t data_offset = 10;
4938732b070SChe-liang Chiou const size_t header_and_checksum_size = TPM_RESPONSE_HEADER_LENGTH + 20;
4948732b070SChe-liang Chiou uint8_t response[COMMAND_BUFFER_SIZE + TPM_PUBEK_SIZE];
4958732b070SChe-liang Chiou size_t response_length = sizeof(response);
4968732b070SChe-liang Chiou uint32_t data_size;
4978732b070SChe-liang Chiou uint32_t err;
4988732b070SChe-liang Chiou
4998732b070SChe-liang Chiou err = tpm_sendrecv_command(command, response, &response_length);
5008732b070SChe-liang Chiou if (err)
5018732b070SChe-liang Chiou return err;
5028732b070SChe-liang Chiou if (unpack_byte_string(response, response_length, "d",
5038732b070SChe-liang Chiou response_size_offset, &data_size))
5048732b070SChe-liang Chiou return TPM_LIB_ERROR;
5058732b070SChe-liang Chiou if (data_size < header_and_checksum_size)
5068732b070SChe-liang Chiou return TPM_LIB_ERROR;
5078732b070SChe-liang Chiou data_size -= header_and_checksum_size;
5088732b070SChe-liang Chiou if (data_size > count)
5098732b070SChe-liang Chiou return TPM_LIB_ERROR;
5108732b070SChe-liang Chiou if (unpack_byte_string(response, response_length, "s",
5118732b070SChe-liang Chiou data_offset, data, data_size))
5128732b070SChe-liang Chiou return TPM_LIB_ERROR;
5138732b070SChe-liang Chiou
5148732b070SChe-liang Chiou return 0;
5158732b070SChe-liang Chiou }
5168732b070SChe-liang Chiou
tpm_force_clear(void)5178732b070SChe-liang Chiou uint32_t tpm_force_clear(void)
5188732b070SChe-liang Chiou {
5198732b070SChe-liang Chiou const uint8_t command[10] = {
5208732b070SChe-liang Chiou 0x0, 0xc1, 0x0, 0x0, 0x0, 0xa, 0x0, 0x0, 0x0, 0x5d,
5218732b070SChe-liang Chiou };
5228732b070SChe-liang Chiou
5238732b070SChe-liang Chiou return tpm_sendrecv_command(command, NULL, NULL);
5248732b070SChe-liang Chiou }
5258732b070SChe-liang Chiou
tpm_physical_enable(void)5268732b070SChe-liang Chiou uint32_t tpm_physical_enable(void)
5278732b070SChe-liang Chiou {
5288732b070SChe-liang Chiou const uint8_t command[10] = {
5298732b070SChe-liang Chiou 0x0, 0xc1, 0x0, 0x0, 0x0, 0xa, 0x0, 0x0, 0x0, 0x6f,
5308732b070SChe-liang Chiou };
5318732b070SChe-liang Chiou
5328732b070SChe-liang Chiou return tpm_sendrecv_command(command, NULL, NULL);
5338732b070SChe-liang Chiou }
5348732b070SChe-liang Chiou
tpm_physical_disable(void)5358732b070SChe-liang Chiou uint32_t tpm_physical_disable(void)
5368732b070SChe-liang Chiou {
5378732b070SChe-liang Chiou const uint8_t command[10] = {
5388732b070SChe-liang Chiou 0x0, 0xc1, 0x0, 0x0, 0x0, 0xa, 0x0, 0x0, 0x0, 0x70,
5398732b070SChe-liang Chiou };
5408732b070SChe-liang Chiou
5418732b070SChe-liang Chiou return tpm_sendrecv_command(command, NULL, NULL);
5428732b070SChe-liang Chiou }
5438732b070SChe-liang Chiou
tpm_physical_set_deactivated(uint8_t state)5448732b070SChe-liang Chiou uint32_t tpm_physical_set_deactivated(uint8_t state)
5458732b070SChe-liang Chiou {
5468732b070SChe-liang Chiou const uint8_t command[11] = {
5478732b070SChe-liang Chiou 0x0, 0xc1, 0x0, 0x0, 0x0, 0xb, 0x0, 0x0, 0x0, 0x72,
5488732b070SChe-liang Chiou };
5498732b070SChe-liang Chiou const size_t state_offset = 10;
5508732b070SChe-liang Chiou uint8_t buf[COMMAND_BUFFER_SIZE];
5518732b070SChe-liang Chiou
5528732b070SChe-liang Chiou if (pack_byte_string(buf, sizeof(buf), "sb",
5538732b070SChe-liang Chiou 0, command, sizeof(command),
5548732b070SChe-liang Chiou state_offset, state))
5558732b070SChe-liang Chiou return TPM_LIB_ERROR;
5568732b070SChe-liang Chiou
5578732b070SChe-liang Chiou return tpm_sendrecv_command(buf, NULL, NULL);
5588732b070SChe-liang Chiou }
5598732b070SChe-liang Chiou
tpm_get_capability(uint32_t cap_area,uint32_t sub_cap,void * cap,size_t count)5608732b070SChe-liang Chiou uint32_t tpm_get_capability(uint32_t cap_area, uint32_t sub_cap,
5618732b070SChe-liang Chiou void *cap, size_t count)
5628732b070SChe-liang Chiou {
5638732b070SChe-liang Chiou const uint8_t command[22] = {
5648732b070SChe-liang Chiou 0x0, 0xc1, /* TPM_TAG */
5658732b070SChe-liang Chiou 0x0, 0x0, 0x0, 0x16, /* parameter size */
5668732b070SChe-liang Chiou 0x0, 0x0, 0x0, 0x65, /* TPM_COMMAND_CODE */
5678732b070SChe-liang Chiou 0x0, 0x0, 0x0, 0x0, /* TPM_CAPABILITY_AREA */
5688732b070SChe-liang Chiou 0x0, 0x0, 0x0, 0x4, /* subcap size */
5698732b070SChe-liang Chiou 0x0, 0x0, 0x0, 0x0, /* subcap value */
5708732b070SChe-liang Chiou };
5718732b070SChe-liang Chiou const size_t cap_area_offset = 10;
5728732b070SChe-liang Chiou const size_t sub_cap_offset = 18;
5738732b070SChe-liang Chiou const size_t cap_offset = 14;
5748732b070SChe-liang Chiou const size_t cap_size_offset = 10;
5758732b070SChe-liang Chiou uint8_t buf[COMMAND_BUFFER_SIZE], response[COMMAND_BUFFER_SIZE];
5768732b070SChe-liang Chiou size_t response_length = sizeof(response);
5778732b070SChe-liang Chiou uint32_t cap_size;
5788732b070SChe-liang Chiou uint32_t err;
5798732b070SChe-liang Chiou
5808732b070SChe-liang Chiou if (pack_byte_string(buf, sizeof(buf), "sdd",
5818732b070SChe-liang Chiou 0, command, sizeof(command),
5828732b070SChe-liang Chiou cap_area_offset, cap_area,
5838732b070SChe-liang Chiou sub_cap_offset, sub_cap))
5848732b070SChe-liang Chiou return TPM_LIB_ERROR;
5858732b070SChe-liang Chiou err = tpm_sendrecv_command(buf, response, &response_length);
5868732b070SChe-liang Chiou if (err)
5878732b070SChe-liang Chiou return err;
5888732b070SChe-liang Chiou if (unpack_byte_string(response, response_length, "d",
5898732b070SChe-liang Chiou cap_size_offset, &cap_size))
5908732b070SChe-liang Chiou return TPM_LIB_ERROR;
5918732b070SChe-liang Chiou if (cap_size > response_length || cap_size > count)
5928732b070SChe-liang Chiou return TPM_LIB_ERROR;
5938732b070SChe-liang Chiou if (unpack_byte_string(response, response_length, "s",
5948732b070SChe-liang Chiou cap_offset, cap, cap_size))
5958732b070SChe-liang Chiou return TPM_LIB_ERROR;
5968732b070SChe-liang Chiou
5978732b070SChe-liang Chiou return 0;
5988732b070SChe-liang Chiou }
599be6c1529SReinhard Pfau
tpm_get_permanent_flags(struct tpm_permanent_flags * pflags)6002132f971SSimon Glass uint32_t tpm_get_permanent_flags(struct tpm_permanent_flags *pflags)
6012132f971SSimon Glass {
6022132f971SSimon Glass const uint8_t command[22] = {
6032132f971SSimon Glass 0x0, 0xc1, /* TPM_TAG */
6042132f971SSimon Glass 0x0, 0x0, 0x0, 0x16, /* parameter size */
6052132f971SSimon Glass 0x0, 0x0, 0x0, 0x65, /* TPM_COMMAND_CODE */
6062132f971SSimon Glass 0x0, 0x0, 0x0, 0x4, /* TPM_CAP_FLAG_PERM */
6072132f971SSimon Glass 0x0, 0x0, 0x0, 0x4, /* subcap size */
6082132f971SSimon Glass 0x0, 0x0, 0x1, 0x8, /* subcap value */
6092132f971SSimon Glass };
610*726c9beeSAndré Draszik const size_t data_size_offset = TPM_HEADER_SIZE;
611*726c9beeSAndré Draszik const size_t data_offset = TPM_HEADER_SIZE + sizeof (uint32_t);
6122132f971SSimon Glass uint8_t response[COMMAND_BUFFER_SIZE];
6132132f971SSimon Glass size_t response_length = sizeof(response);
6142132f971SSimon Glass uint32_t err;
615*726c9beeSAndré Draszik uint32_t data_size;
6162132f971SSimon Glass
6172132f971SSimon Glass err = tpm_sendrecv_command(command, response, &response_length);
6182132f971SSimon Glass if (err)
6192132f971SSimon Glass return err;
620*726c9beeSAndré Draszik if (unpack_byte_string(response, response_length, "d",
621*726c9beeSAndré Draszik data_size_offset, &data_size))
622*726c9beeSAndré Draszik return TPM_LIB_ERROR;
623*726c9beeSAndré Draszik if (data_size < sizeof(*pflags))
624*726c9beeSAndré Draszik return TPM_LIB_ERROR;
625*726c9beeSAndré Draszik if (unpack_byte_string(response, response_length, "s",
626*726c9beeSAndré Draszik data_offset, pflags, sizeof(*pflags)))
627*726c9beeSAndré Draszik return TPM_LIB_ERROR;
6282132f971SSimon Glass
6292132f971SSimon Glass return 0;
6302132f971SSimon Glass }
6312132f971SSimon Glass
tpm_get_permissions(uint32_t index,uint32_t * perm)6322132f971SSimon Glass uint32_t tpm_get_permissions(uint32_t index, uint32_t *perm)
6332132f971SSimon Glass {
6342132f971SSimon Glass const uint8_t command[22] = {
6352132f971SSimon Glass 0x0, 0xc1, /* TPM_TAG */
6362132f971SSimon Glass 0x0, 0x0, 0x0, 0x16, /* parameter size */
6372132f971SSimon Glass 0x0, 0x0, 0x0, 0x65, /* TPM_COMMAND_CODE */
6382132f971SSimon Glass 0x0, 0x0, 0x0, 0x11,
6392132f971SSimon Glass 0x0, 0x0, 0x0, 0x4,
6402132f971SSimon Glass };
6412132f971SSimon Glass const size_t index_offset = 18;
6422132f971SSimon Glass const size_t perm_offset = 60;
6432132f971SSimon Glass uint8_t buf[COMMAND_BUFFER_SIZE], response[COMMAND_BUFFER_SIZE];
6442132f971SSimon Glass size_t response_length = sizeof(response);
6452132f971SSimon Glass uint32_t err;
6462132f971SSimon Glass
6472132f971SSimon Glass if (pack_byte_string(buf, sizeof(buf), "d", 0, command, sizeof(command),
6482132f971SSimon Glass index_offset, index))
6492132f971SSimon Glass return TPM_LIB_ERROR;
6502132f971SSimon Glass err = tpm_sendrecv_command(buf, response, &response_length);
6512132f971SSimon Glass if (err)
6522132f971SSimon Glass return err;
6532132f971SSimon Glass if (unpack_byte_string(response, response_length, "d",
6542132f971SSimon Glass perm_offset, perm))
6552132f971SSimon Glass return TPM_LIB_ERROR;
6562132f971SSimon Glass
6572132f971SSimon Glass return 0;
6582132f971SSimon Glass }
6592132f971SSimon Glass
6607690be35SMario Six #ifdef CONFIG_TPM_FLUSH_RESOURCES
tpm_flush_specific(uint32_t key_handle,uint32_t resource_type)6617690be35SMario Six uint32_t tpm_flush_specific(uint32_t key_handle, uint32_t resource_type)
6627690be35SMario Six {
6637690be35SMario Six const uint8_t command[18] = {
6647690be35SMario Six 0x00, 0xc1, /* TPM_TAG */
6657690be35SMario Six 0x00, 0x00, 0x00, 0x12, /* parameter size */
6667690be35SMario Six 0x00, 0x00, 0x00, 0xba, /* TPM_COMMAND_CODE */
6677690be35SMario Six 0x00, 0x00, 0x00, 0x00, /* key handle */
6687690be35SMario Six 0x00, 0x00, 0x00, 0x00, /* resource type */
6697690be35SMario Six };
6707690be35SMario Six const size_t key_handle_offset = 10;
6717690be35SMario Six const size_t resource_type_offset = 14;
6727690be35SMario Six uint8_t buf[COMMAND_BUFFER_SIZE], response[COMMAND_BUFFER_SIZE];
6737690be35SMario Six size_t response_length = sizeof(response);
6747690be35SMario Six uint32_t err;
6757690be35SMario Six
6767690be35SMario Six if (pack_byte_string(buf, sizeof(buf), "sdd",
6777690be35SMario Six 0, command, sizeof(command),
6787690be35SMario Six key_handle_offset, key_handle,
6797690be35SMario Six resource_type_offset, resource_type))
6807690be35SMario Six return TPM_LIB_ERROR;
6817690be35SMario Six
6827690be35SMario Six err = tpm_sendrecv_command(buf, response, &response_length);
6837690be35SMario Six if (err)
6847690be35SMario Six return err;
6857690be35SMario Six return 0;
6867690be35SMario Six }
6877690be35SMario Six #endif /* CONFIG_TPM_FLUSH_RESOURCES */
6887690be35SMario Six
689be6c1529SReinhard Pfau #ifdef CONFIG_TPM_AUTH_SESSIONS
690be6c1529SReinhard Pfau
691be6c1529SReinhard Pfau /**
692be6c1529SReinhard Pfau * Fill an authentication block in a request.
693be6c1529SReinhard Pfau * This func can create the first as well as the second auth block (for
694be6c1529SReinhard Pfau * double authorized commands).
695be6c1529SReinhard Pfau *
696be6c1529SReinhard Pfau * @param request pointer to the request (w/ uninitialised auth data)
697be6c1529SReinhard Pfau * @param request_len0 length of the request without auth data
698be6c1529SReinhard Pfau * @param handles_len length of the handles area in request
699be6c1529SReinhard Pfau * @param auth_session pointer to the (valid) auth session to be used
700be6c1529SReinhard Pfau * @param request_auth pointer to the auth block of the request to be filled
701be6c1529SReinhard Pfau * @param auth authentication data (HMAC key)
702be6c1529SReinhard Pfau */
create_request_auth(const void * request,size_t request_len0,size_t handles_len,struct session_data * auth_session,void * request_auth,const void * auth)703be6c1529SReinhard Pfau static uint32_t create_request_auth(const void *request, size_t request_len0,
704be6c1529SReinhard Pfau size_t handles_len,
705be6c1529SReinhard Pfau struct session_data *auth_session,
706be6c1529SReinhard Pfau void *request_auth, const void *auth)
707be6c1529SReinhard Pfau {
708be6c1529SReinhard Pfau uint8_t hmac_data[DIGEST_LENGTH * 3 + 1];
709be6c1529SReinhard Pfau sha1_context hash_ctx;
710be6c1529SReinhard Pfau const size_t command_code_offset = 6;
711be6c1529SReinhard Pfau const size_t auth_nonce_odd_offset = 4;
712be6c1529SReinhard Pfau const size_t auth_continue_offset = 24;
713be6c1529SReinhard Pfau const size_t auth_auth_offset = 25;
714be6c1529SReinhard Pfau
715be6c1529SReinhard Pfau if (!auth_session || !auth_session->valid)
716be6c1529SReinhard Pfau return TPM_LIB_ERROR;
717be6c1529SReinhard Pfau
718be6c1529SReinhard Pfau sha1_starts(&hash_ctx);
719be6c1529SReinhard Pfau sha1_update(&hash_ctx, request + command_code_offset, 4);
720be6c1529SReinhard Pfau if (request_len0 > TPM_REQUEST_HEADER_LENGTH + handles_len)
721be6c1529SReinhard Pfau sha1_update(&hash_ctx,
722be6c1529SReinhard Pfau request + TPM_REQUEST_HEADER_LENGTH + handles_len,
723be6c1529SReinhard Pfau request_len0 - TPM_REQUEST_HEADER_LENGTH
724be6c1529SReinhard Pfau - handles_len);
725be6c1529SReinhard Pfau sha1_finish(&hash_ctx, hmac_data);
726be6c1529SReinhard Pfau
727be6c1529SReinhard Pfau sha1_starts(&hash_ctx);
728be6c1529SReinhard Pfau sha1_update(&hash_ctx, auth_session->nonce_odd, DIGEST_LENGTH);
729be6c1529SReinhard Pfau sha1_update(&hash_ctx, hmac_data, sizeof(hmac_data));
730be6c1529SReinhard Pfau sha1_finish(&hash_ctx, auth_session->nonce_odd);
731be6c1529SReinhard Pfau
732be6c1529SReinhard Pfau if (pack_byte_string(request_auth, TPM_REQUEST_AUTH_LENGTH, "dsb",
733be6c1529SReinhard Pfau 0, auth_session->handle,
734be6c1529SReinhard Pfau auth_nonce_odd_offset, auth_session->nonce_odd,
735be6c1529SReinhard Pfau DIGEST_LENGTH,
736be6c1529SReinhard Pfau auth_continue_offset, 1))
737be6c1529SReinhard Pfau return TPM_LIB_ERROR;
738be6c1529SReinhard Pfau if (pack_byte_string(hmac_data, sizeof(hmac_data), "ss",
739be6c1529SReinhard Pfau DIGEST_LENGTH,
740be6c1529SReinhard Pfau auth_session->nonce_even,
741be6c1529SReinhard Pfau DIGEST_LENGTH,
742be6c1529SReinhard Pfau 2 * DIGEST_LENGTH,
743be6c1529SReinhard Pfau request_auth + auth_nonce_odd_offset,
744be6c1529SReinhard Pfau DIGEST_LENGTH + 1))
745be6c1529SReinhard Pfau return TPM_LIB_ERROR;
746be6c1529SReinhard Pfau sha1_hmac(auth, DIGEST_LENGTH, hmac_data, sizeof(hmac_data),
747be6c1529SReinhard Pfau request_auth + auth_auth_offset);
748be6c1529SReinhard Pfau
749be6c1529SReinhard Pfau return TPM_SUCCESS;
750be6c1529SReinhard Pfau }
751be6c1529SReinhard Pfau
752be6c1529SReinhard Pfau /**
753be6c1529SReinhard Pfau * Verify an authentication block in a response.
754be6c1529SReinhard Pfau * Since this func updates the nonce_even in the session data it has to be
755be6c1529SReinhard Pfau * called when receiving a succesfull AUTH response.
756be6c1529SReinhard Pfau * This func can verify the first as well as the second auth block (for
757be6c1529SReinhard Pfau * double authorized commands).
758be6c1529SReinhard Pfau *
759be6c1529SReinhard Pfau * @param command_code command code of the request
760be6c1529SReinhard Pfau * @param response pointer to the request (w/ uninitialised auth data)
761be6c1529SReinhard Pfau * @param handles_len length of the handles area in response
762be6c1529SReinhard Pfau * @param auth_session pointer to the (valid) auth session to be used
763be6c1529SReinhard Pfau * @param response_auth pointer to the auth block of the response to be verified
764be6c1529SReinhard Pfau * @param auth authentication data (HMAC key)
765be6c1529SReinhard Pfau */
verify_response_auth(uint32_t command_code,const void * response,size_t response_len0,size_t handles_len,struct session_data * auth_session,const void * response_auth,const void * auth)766be6c1529SReinhard Pfau static uint32_t verify_response_auth(uint32_t command_code,
767be6c1529SReinhard Pfau const void *response, size_t response_len0,
768be6c1529SReinhard Pfau size_t handles_len,
769be6c1529SReinhard Pfau struct session_data *auth_session,
770be6c1529SReinhard Pfau const void *response_auth, const void *auth)
771be6c1529SReinhard Pfau {
772be6c1529SReinhard Pfau uint8_t hmac_data[DIGEST_LENGTH * 3 + 1];
773be6c1529SReinhard Pfau uint8_t computed_auth[DIGEST_LENGTH];
774be6c1529SReinhard Pfau sha1_context hash_ctx;
775be6c1529SReinhard Pfau const size_t return_code_offset = 6;
776be6c1529SReinhard Pfau const size_t auth_continue_offset = 20;
777be6c1529SReinhard Pfau const size_t auth_auth_offset = 21;
778be6c1529SReinhard Pfau uint8_t auth_continue;
779be6c1529SReinhard Pfau
780be6c1529SReinhard Pfau if (!auth_session || !auth_session->valid)
781be6c1529SReinhard Pfau return TPM_AUTHFAIL;
782be6c1529SReinhard Pfau if (pack_byte_string(hmac_data, sizeof(hmac_data), "d",
783be6c1529SReinhard Pfau 0, command_code))
784be6c1529SReinhard Pfau return TPM_LIB_ERROR;
785be6c1529SReinhard Pfau if (response_len0 < TPM_RESPONSE_HEADER_LENGTH)
786be6c1529SReinhard Pfau return TPM_LIB_ERROR;
787be6c1529SReinhard Pfau
788be6c1529SReinhard Pfau sha1_starts(&hash_ctx);
789be6c1529SReinhard Pfau sha1_update(&hash_ctx, response + return_code_offset, 4);
790be6c1529SReinhard Pfau sha1_update(&hash_ctx, hmac_data, 4);
791be6c1529SReinhard Pfau if (response_len0 > TPM_RESPONSE_HEADER_LENGTH + handles_len)
792be6c1529SReinhard Pfau sha1_update(&hash_ctx,
793be6c1529SReinhard Pfau response + TPM_RESPONSE_HEADER_LENGTH + handles_len,
794be6c1529SReinhard Pfau response_len0 - TPM_RESPONSE_HEADER_LENGTH
795be6c1529SReinhard Pfau - handles_len);
796be6c1529SReinhard Pfau sha1_finish(&hash_ctx, hmac_data);
797be6c1529SReinhard Pfau
798be6c1529SReinhard Pfau memcpy(auth_session->nonce_even, response_auth, DIGEST_LENGTH);
799be6c1529SReinhard Pfau auth_continue = ((uint8_t *)response_auth)[auth_continue_offset];
800be6c1529SReinhard Pfau if (pack_byte_string(hmac_data, sizeof(hmac_data), "ssb",
801be6c1529SReinhard Pfau DIGEST_LENGTH,
802be6c1529SReinhard Pfau response_auth,
803be6c1529SReinhard Pfau DIGEST_LENGTH,
804be6c1529SReinhard Pfau 2 * DIGEST_LENGTH,
805be6c1529SReinhard Pfau auth_session->nonce_odd,
806be6c1529SReinhard Pfau DIGEST_LENGTH,
807be6c1529SReinhard Pfau 3 * DIGEST_LENGTH,
808be6c1529SReinhard Pfau auth_continue))
809be6c1529SReinhard Pfau return TPM_LIB_ERROR;
810be6c1529SReinhard Pfau
811be6c1529SReinhard Pfau sha1_hmac(auth, DIGEST_LENGTH, hmac_data, sizeof(hmac_data),
812be6c1529SReinhard Pfau computed_auth);
813be6c1529SReinhard Pfau
814be6c1529SReinhard Pfau if (memcmp(computed_auth, response_auth + auth_auth_offset,
815be6c1529SReinhard Pfau DIGEST_LENGTH))
816be6c1529SReinhard Pfau return TPM_AUTHFAIL;
817be6c1529SReinhard Pfau
818be6c1529SReinhard Pfau return TPM_SUCCESS;
819be6c1529SReinhard Pfau }
820be6c1529SReinhard Pfau
821be6c1529SReinhard Pfau
tpm_terminate_auth_session(uint32_t auth_handle)822be6c1529SReinhard Pfau uint32_t tpm_terminate_auth_session(uint32_t auth_handle)
823be6c1529SReinhard Pfau {
824be6c1529SReinhard Pfau const uint8_t command[18] = {
825be6c1529SReinhard Pfau 0x00, 0xc1, /* TPM_TAG */
826be6c1529SReinhard Pfau 0x00, 0x00, 0x00, 0x00, /* parameter size */
827be6c1529SReinhard Pfau 0x00, 0x00, 0x00, 0xba, /* TPM_COMMAND_CODE */
828be6c1529SReinhard Pfau 0x00, 0x00, 0x00, 0x00, /* TPM_HANDLE */
829be6c1529SReinhard Pfau 0x00, 0x00, 0x00, 0x02, /* TPM_RESSOURCE_TYPE */
830be6c1529SReinhard Pfau };
831be6c1529SReinhard Pfau const size_t req_handle_offset = TPM_REQUEST_HEADER_LENGTH;
832be6c1529SReinhard Pfau uint8_t request[COMMAND_BUFFER_SIZE];
833be6c1529SReinhard Pfau
834be6c1529SReinhard Pfau if (pack_byte_string(request, sizeof(request), "sd",
835be6c1529SReinhard Pfau 0, command, sizeof(command),
836be6c1529SReinhard Pfau req_handle_offset, auth_handle))
837be6c1529SReinhard Pfau return TPM_LIB_ERROR;
838be6c1529SReinhard Pfau if (oiap_session.valid && oiap_session.handle == auth_handle)
839be6c1529SReinhard Pfau oiap_session.valid = 0;
840be6c1529SReinhard Pfau
841be6c1529SReinhard Pfau return tpm_sendrecv_command(request, NULL, NULL);
842be6c1529SReinhard Pfau }
843be6c1529SReinhard Pfau
tpm_end_oiap(void)844be6c1529SReinhard Pfau uint32_t tpm_end_oiap(void)
845be6c1529SReinhard Pfau {
846be6c1529SReinhard Pfau uint32_t err = TPM_SUCCESS;
847be6c1529SReinhard Pfau if (oiap_session.valid)
848be6c1529SReinhard Pfau err = tpm_terminate_auth_session(oiap_session.handle);
849be6c1529SReinhard Pfau return err;
850be6c1529SReinhard Pfau }
851be6c1529SReinhard Pfau
tpm_oiap(uint32_t * auth_handle)852be6c1529SReinhard Pfau uint32_t tpm_oiap(uint32_t *auth_handle)
853be6c1529SReinhard Pfau {
854be6c1529SReinhard Pfau const uint8_t command[10] = {
855be6c1529SReinhard Pfau 0x00, 0xc1, /* TPM_TAG */
856be6c1529SReinhard Pfau 0x00, 0x00, 0x00, 0x0a, /* parameter size */
857be6c1529SReinhard Pfau 0x00, 0x00, 0x00, 0x0a, /* TPM_COMMAND_CODE */
858be6c1529SReinhard Pfau };
859be6c1529SReinhard Pfau const size_t res_auth_handle_offset = TPM_RESPONSE_HEADER_LENGTH;
860be6c1529SReinhard Pfau const size_t res_nonce_even_offset = TPM_RESPONSE_HEADER_LENGTH + 4;
861be6c1529SReinhard Pfau uint8_t response[COMMAND_BUFFER_SIZE];
862be6c1529SReinhard Pfau size_t response_length = sizeof(response);
863be6c1529SReinhard Pfau uint32_t err;
864be6c1529SReinhard Pfau
865be6c1529SReinhard Pfau if (oiap_session.valid)
866be6c1529SReinhard Pfau tpm_terminate_auth_session(oiap_session.handle);
867be6c1529SReinhard Pfau
868be6c1529SReinhard Pfau err = tpm_sendrecv_command(command, response, &response_length);
869be6c1529SReinhard Pfau if (err)
870be6c1529SReinhard Pfau return err;
871be6c1529SReinhard Pfau if (unpack_byte_string(response, response_length, "ds",
872be6c1529SReinhard Pfau res_auth_handle_offset, &oiap_session.handle,
873be6c1529SReinhard Pfau res_nonce_even_offset, &oiap_session.nonce_even,
874be6c1529SReinhard Pfau (uint32_t)DIGEST_LENGTH))
875be6c1529SReinhard Pfau return TPM_LIB_ERROR;
876be6c1529SReinhard Pfau oiap_session.valid = 1;
877be6c1529SReinhard Pfau if (auth_handle)
878be6c1529SReinhard Pfau *auth_handle = oiap_session.handle;
879be6c1529SReinhard Pfau return 0;
880be6c1529SReinhard Pfau }
881be6c1529SReinhard Pfau
tpm_load_key2_oiap(uint32_t parent_handle,const void * key,size_t key_length,const void * parent_key_usage_auth,uint32_t * key_handle)882be6c1529SReinhard Pfau uint32_t tpm_load_key2_oiap(uint32_t parent_handle,
883be6c1529SReinhard Pfau const void *key, size_t key_length,
884be6c1529SReinhard Pfau const void *parent_key_usage_auth,
885be6c1529SReinhard Pfau uint32_t *key_handle)
886be6c1529SReinhard Pfau {
887be6c1529SReinhard Pfau const uint8_t command[14] = {
888be6c1529SReinhard Pfau 0x00, 0xc2, /* TPM_TAG */
889be6c1529SReinhard Pfau 0x00, 0x00, 0x00, 0x00, /* parameter size */
890be6c1529SReinhard Pfau 0x00, 0x00, 0x00, 0x41, /* TPM_COMMAND_CODE */
891be6c1529SReinhard Pfau 0x00, 0x00, 0x00, 0x00, /* parent handle */
892be6c1529SReinhard Pfau };
893be6c1529SReinhard Pfau const size_t req_size_offset = 2;
894be6c1529SReinhard Pfau const size_t req_parent_handle_offset = TPM_REQUEST_HEADER_LENGTH;
895be6c1529SReinhard Pfau const size_t req_key_offset = TPM_REQUEST_HEADER_LENGTH + 4;
896be6c1529SReinhard Pfau const size_t res_handle_offset = TPM_RESPONSE_HEADER_LENGTH;
897be6c1529SReinhard Pfau uint8_t request[sizeof(command) + TPM_KEY12_MAX_LENGTH
898be6c1529SReinhard Pfau + TPM_REQUEST_AUTH_LENGTH];
899be6c1529SReinhard Pfau uint8_t response[COMMAND_BUFFER_SIZE];
900be6c1529SReinhard Pfau size_t response_length = sizeof(response);
901be6c1529SReinhard Pfau uint32_t err;
902be6c1529SReinhard Pfau
903be6c1529SReinhard Pfau if (!oiap_session.valid) {
904be6c1529SReinhard Pfau err = tpm_oiap(NULL);
905be6c1529SReinhard Pfau if (err)
906be6c1529SReinhard Pfau return err;
907be6c1529SReinhard Pfau }
908be6c1529SReinhard Pfau if (pack_byte_string(request, sizeof(request), "sdds",
909be6c1529SReinhard Pfau 0, command, sizeof(command),
910be6c1529SReinhard Pfau req_size_offset,
911be6c1529SReinhard Pfau sizeof(command) + key_length
912be6c1529SReinhard Pfau + TPM_REQUEST_AUTH_LENGTH,
913be6c1529SReinhard Pfau req_parent_handle_offset, parent_handle,
914be6c1529SReinhard Pfau req_key_offset, key, key_length
915be6c1529SReinhard Pfau ))
916be6c1529SReinhard Pfau return TPM_LIB_ERROR;
917be6c1529SReinhard Pfau
918be6c1529SReinhard Pfau err = create_request_auth(request, sizeof(command) + key_length, 4,
919be6c1529SReinhard Pfau &oiap_session,
920be6c1529SReinhard Pfau request + sizeof(command) + key_length,
921be6c1529SReinhard Pfau parent_key_usage_auth);
922be6c1529SReinhard Pfau if (err)
923be6c1529SReinhard Pfau return err;
924be6c1529SReinhard Pfau err = tpm_sendrecv_command(request, response, &response_length);
925be6c1529SReinhard Pfau if (err) {
926be6c1529SReinhard Pfau if (err == TPM_AUTHFAIL)
927be6c1529SReinhard Pfau oiap_session.valid = 0;
928be6c1529SReinhard Pfau return err;
929be6c1529SReinhard Pfau }
930be6c1529SReinhard Pfau
931be6c1529SReinhard Pfau err = verify_response_auth(0x00000041, response,
932be6c1529SReinhard Pfau response_length - TPM_RESPONSE_AUTH_LENGTH,
933be6c1529SReinhard Pfau 4, &oiap_session,
934be6c1529SReinhard Pfau response + response_length - TPM_RESPONSE_AUTH_LENGTH,
935be6c1529SReinhard Pfau parent_key_usage_auth);
936be6c1529SReinhard Pfau if (err)
937be6c1529SReinhard Pfau return err;
938be6c1529SReinhard Pfau
939be6c1529SReinhard Pfau if (key_handle) {
940be6c1529SReinhard Pfau if (unpack_byte_string(response, response_length, "d",
941be6c1529SReinhard Pfau res_handle_offset, key_handle))
942be6c1529SReinhard Pfau return TPM_LIB_ERROR;
943be6c1529SReinhard Pfau }
944be6c1529SReinhard Pfau
945be6c1529SReinhard Pfau return 0;
946be6c1529SReinhard Pfau }
947be6c1529SReinhard Pfau
tpm_get_pub_key_oiap(uint32_t key_handle,const void * usage_auth,void * pubkey,size_t * pubkey_len)948be6c1529SReinhard Pfau uint32_t tpm_get_pub_key_oiap(uint32_t key_handle, const void *usage_auth,
949be6c1529SReinhard Pfau void *pubkey, size_t *pubkey_len)
950be6c1529SReinhard Pfau {
951be6c1529SReinhard Pfau const uint8_t command[14] = {
952be6c1529SReinhard Pfau 0x00, 0xc2, /* TPM_TAG */
953be6c1529SReinhard Pfau 0x00, 0x00, 0x00, 0x00, /* parameter size */
954be6c1529SReinhard Pfau 0x00, 0x00, 0x00, 0x21, /* TPM_COMMAND_CODE */
955be6c1529SReinhard Pfau 0x00, 0x00, 0x00, 0x00, /* key handle */
956be6c1529SReinhard Pfau };
957be6c1529SReinhard Pfau const size_t req_size_offset = 2;
958be6c1529SReinhard Pfau const size_t req_key_handle_offset = TPM_REQUEST_HEADER_LENGTH;
959be6c1529SReinhard Pfau const size_t res_pubkey_offset = TPM_RESPONSE_HEADER_LENGTH;
960be6c1529SReinhard Pfau uint8_t request[sizeof(command) + TPM_REQUEST_AUTH_LENGTH];
961be6c1529SReinhard Pfau uint8_t response[TPM_RESPONSE_HEADER_LENGTH + TPM_PUBKEY_MAX_LENGTH
962be6c1529SReinhard Pfau + TPM_RESPONSE_AUTH_LENGTH];
963be6c1529SReinhard Pfau size_t response_length = sizeof(response);
964be6c1529SReinhard Pfau uint32_t err;
965be6c1529SReinhard Pfau
966be6c1529SReinhard Pfau if (!oiap_session.valid) {
967be6c1529SReinhard Pfau err = tpm_oiap(NULL);
968be6c1529SReinhard Pfau if (err)
969be6c1529SReinhard Pfau return err;
970be6c1529SReinhard Pfau }
971be6c1529SReinhard Pfau if (pack_byte_string(request, sizeof(request), "sdd",
972be6c1529SReinhard Pfau 0, command, sizeof(command),
973be6c1529SReinhard Pfau req_size_offset,
974be6c1529SReinhard Pfau (uint32_t)(sizeof(command)
975be6c1529SReinhard Pfau + TPM_REQUEST_AUTH_LENGTH),
976be6c1529SReinhard Pfau req_key_handle_offset, key_handle
977be6c1529SReinhard Pfau ))
978be6c1529SReinhard Pfau return TPM_LIB_ERROR;
979be6c1529SReinhard Pfau err = create_request_auth(request, sizeof(command), 4, &oiap_session,
980be6c1529SReinhard Pfau request + sizeof(command), usage_auth);
981be6c1529SReinhard Pfau if (err)
982be6c1529SReinhard Pfau return err;
983be6c1529SReinhard Pfau err = tpm_sendrecv_command(request, response, &response_length);
984be6c1529SReinhard Pfau if (err) {
985be6c1529SReinhard Pfau if (err == TPM_AUTHFAIL)
986be6c1529SReinhard Pfau oiap_session.valid = 0;
987be6c1529SReinhard Pfau return err;
988be6c1529SReinhard Pfau }
989be6c1529SReinhard Pfau err = verify_response_auth(0x00000021, response,
990be6c1529SReinhard Pfau response_length - TPM_RESPONSE_AUTH_LENGTH,
991be6c1529SReinhard Pfau 0, &oiap_session,
992be6c1529SReinhard Pfau response + response_length - TPM_RESPONSE_AUTH_LENGTH,
993be6c1529SReinhard Pfau usage_auth);
994be6c1529SReinhard Pfau if (err)
995be6c1529SReinhard Pfau return err;
996be6c1529SReinhard Pfau
997be6c1529SReinhard Pfau if (pubkey) {
998be6c1529SReinhard Pfau if ((response_length - TPM_RESPONSE_HEADER_LENGTH
999be6c1529SReinhard Pfau - TPM_RESPONSE_AUTH_LENGTH) > *pubkey_len)
1000be6c1529SReinhard Pfau return TPM_LIB_ERROR;
1001be6c1529SReinhard Pfau *pubkey_len = response_length - TPM_RESPONSE_HEADER_LENGTH
1002be6c1529SReinhard Pfau - TPM_RESPONSE_AUTH_LENGTH;
1003be6c1529SReinhard Pfau memcpy(pubkey, response + res_pubkey_offset,
1004be6c1529SReinhard Pfau response_length - TPM_RESPONSE_HEADER_LENGTH
1005be6c1529SReinhard Pfau - TPM_RESPONSE_AUTH_LENGTH);
1006be6c1529SReinhard Pfau }
1007be6c1529SReinhard Pfau
1008be6c1529SReinhard Pfau return 0;
1009be6c1529SReinhard Pfau }
1010be6c1529SReinhard Pfau
10110f4b2ba1Smario.six@gdsys.cc #ifdef CONFIG_TPM_LOAD_KEY_BY_SHA1
tpm_find_key_sha1(const uint8_t auth[20],const uint8_t pubkey_digest[20],uint32_t * handle)10120f4b2ba1Smario.six@gdsys.cc uint32_t tpm_find_key_sha1(const uint8_t auth[20], const uint8_t
10130f4b2ba1Smario.six@gdsys.cc pubkey_digest[20], uint32_t *handle)
10140f4b2ba1Smario.six@gdsys.cc {
10150f4b2ba1Smario.six@gdsys.cc uint16_t key_count;
10160f4b2ba1Smario.six@gdsys.cc uint32_t key_handles[10];
10170f4b2ba1Smario.six@gdsys.cc uint8_t buf[288];
10180f4b2ba1Smario.six@gdsys.cc uint8_t *ptr;
10190f4b2ba1Smario.six@gdsys.cc uint32_t err;
10200f4b2ba1Smario.six@gdsys.cc uint8_t digest[20];
10210f4b2ba1Smario.six@gdsys.cc size_t buf_len;
10220f4b2ba1Smario.six@gdsys.cc unsigned int i;
10230f4b2ba1Smario.six@gdsys.cc
10240f4b2ba1Smario.six@gdsys.cc /* fetch list of already loaded keys in the TPM */
10250f4b2ba1Smario.six@gdsys.cc err = tpm_get_capability(TPM_CAP_HANDLE, TPM_RT_KEY, buf, sizeof(buf));
10260f4b2ba1Smario.six@gdsys.cc if (err)
10270f4b2ba1Smario.six@gdsys.cc return -1;
10280f4b2ba1Smario.six@gdsys.cc key_count = get_unaligned_be16(buf);
10290f4b2ba1Smario.six@gdsys.cc ptr = buf + 2;
10300f4b2ba1Smario.six@gdsys.cc for (i = 0; i < key_count; ++i, ptr += 4)
10310f4b2ba1Smario.six@gdsys.cc key_handles[i] = get_unaligned_be32(ptr);
10320f4b2ba1Smario.six@gdsys.cc
10330f4b2ba1Smario.six@gdsys.cc /* now search a(/ the) key which we can access with the given auth */
10340f4b2ba1Smario.six@gdsys.cc for (i = 0; i < key_count; ++i) {
10350f4b2ba1Smario.six@gdsys.cc buf_len = sizeof(buf);
10360f4b2ba1Smario.six@gdsys.cc err = tpm_get_pub_key_oiap(key_handles[i], auth, buf, &buf_len);
10370f4b2ba1Smario.six@gdsys.cc if (err && err != TPM_AUTHFAIL)
10380f4b2ba1Smario.six@gdsys.cc return -1;
10390f4b2ba1Smario.six@gdsys.cc if (err)
10400f4b2ba1Smario.six@gdsys.cc continue;
10410f4b2ba1Smario.six@gdsys.cc sha1_csum(buf, buf_len, digest);
10420f4b2ba1Smario.six@gdsys.cc if (!memcmp(digest, pubkey_digest, 20)) {
10430f4b2ba1Smario.six@gdsys.cc *handle = key_handles[i];
10440f4b2ba1Smario.six@gdsys.cc return 0;
10450f4b2ba1Smario.six@gdsys.cc }
10460f4b2ba1Smario.six@gdsys.cc }
10470f4b2ba1Smario.six@gdsys.cc return 1;
10480f4b2ba1Smario.six@gdsys.cc }
10490f4b2ba1Smario.six@gdsys.cc #endif /* CONFIG_TPM_LOAD_KEY_BY_SHA1 */
10500f4b2ba1Smario.six@gdsys.cc
1051be6c1529SReinhard Pfau #endif /* CONFIG_TPM_AUTH_SESSIONS */
1052