X-Git-Url: http://review.tizen.org/git/?a=blobdiff_plain;f=lib%2Ftpm.c;h=bc9652d8e4eeecc7dcc85bfc941e4efdd5919716;hb=83d290c56fab2d38cd1ab4c4cc7099559c1d5046;hp=cd7f88f2204e9119f0b24b6a7b98cdd1e441a193;hpb=0f4b2ba1762d74c0b5520d99a58796d6ca78abf0;p=platform%2Fkernel%2Fu-boot.git diff --git a/lib/tpm.c b/lib/tpm.c index cd7f88f..bc9652d 100644 --- a/lib/tpm.c +++ b/lib/tpm.c @@ -1,8 +1,7 @@ +// SPDX-License-Identifier: GPL-2.0+ /* * Copyright (c) 2013 The Chromium OS Authors. * Coypright (c) 2013 Guntermann & Drunck GmbH - * - * SPDX-License-Identifier: GPL-2.0+ */ #include @@ -92,11 +91,14 @@ int pack_byte_string(uint8_t *str, size_t size, const char *format, ...) break; default: debug("Couldn't recognize format string\n"); + va_end(args); return -1; } - if (offset + length > size) + if (offset + length > size) { + va_end(args); return -1; + } switch (*format) { case 'b': @@ -163,12 +165,15 @@ int unpack_byte_string(const uint8_t *str, size_t size, const char *format, ...) length = va_arg(args, uint32_t); break; default: + va_end(args); debug("Couldn't recognize format string\n"); return -1; } - if (offset + length > size) + if (offset + length > size) { + va_end(args); return -1; + } switch (*format) { case 'b': @@ -230,10 +235,9 @@ static uint32_t tpm_sendrecv_command(const void *command, void *response, size_t *size_ptr) { struct udevice *dev; - int ret; + int err, ret; uint8_t response_buffer[COMMAND_BUFFER_SIZE]; size_t response_length; - uint32_t err; if (response) { response_length = *size_ptr; @@ -605,14 +609,24 @@ uint32_t tpm_get_permanent_flags(struct tpm_permanent_flags *pflags) 0x0, 0x0, 0x0, 0x4, /* subcap size */ 0x0, 0x0, 0x1, 0x8, /* subcap value */ }; + const size_t data_size_offset = TPM_HEADER_SIZE; + const size_t data_offset = TPM_HEADER_SIZE + sizeof (uint32_t); uint8_t response[COMMAND_BUFFER_SIZE]; size_t response_length = sizeof(response); uint32_t err; + uint32_t data_size; err = tpm_sendrecv_command(command, response, &response_length); if (err) return err; - memcpy(pflags, response + TPM_HEADER_SIZE, sizeof(*pflags)); + if (unpack_byte_string(response, response_length, "d", + data_size_offset, &data_size)) + return TPM_LIB_ERROR; + if (data_size < sizeof(*pflags)) + return TPM_LIB_ERROR; + if (unpack_byte_string(response, response_length, "s", + data_offset, pflags, sizeof(*pflags))) + return TPM_LIB_ERROR; return 0; } @@ -1037,3 +1051,46 @@ uint32_t tpm_find_key_sha1(const uint8_t auth[20], const uint8_t #endif /* CONFIG_TPM_LOAD_KEY_BY_SHA1 */ #endif /* CONFIG_TPM_AUTH_SESSIONS */ + +uint32_t tpm_get_random(void *data, uint32_t count) +{ + const uint8_t command[14] = { + 0x0, 0xc1, /* TPM_TAG */ + 0x0, 0x0, 0x0, 0xe, /* parameter size */ + 0x0, 0x0, 0x0, 0x46, /* TPM_COMMAND_CODE */ + }; + const size_t length_offset = 10; + const size_t data_size_offset = 10; + const size_t data_offset = 14; + uint8_t buf[COMMAND_BUFFER_SIZE], response[COMMAND_BUFFER_SIZE]; + size_t response_length = sizeof(response); + uint32_t data_size; + uint8_t *out = data; + + while (count > 0) { + uint32_t this_bytes = min((size_t)count, + sizeof (response) - data_offset); + uint32_t err; + + if (pack_byte_string(buf, sizeof(buf), "sd", + 0, command, sizeof(command), + length_offset, this_bytes)) + return TPM_LIB_ERROR; + err = tpm_sendrecv_command(buf, response, &response_length); + if (err) + return err; + if (unpack_byte_string(response, response_length, "d", + data_size_offset, &data_size)) + return TPM_LIB_ERROR; + if (data_size > count) + return TPM_LIB_ERROR; + if (unpack_byte_string(response, response_length, "s", + data_offset, out, data_size)) + return TPM_LIB_ERROR; + + count -= data_size; + out += data_size; + } + + return 0; +}