summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndré Draszik <adraszik@tycoint.com>2017-10-03 16:55:52 +0100
committerSimon Glass <sjg@chromium.org>2017-11-17 07:15:40 -0700
commit3c6050277b54f536e7effbe850dcc970a27387ab (patch)
tree0060f5315a771e64bff35445700b4db84d3a72f5
parente8155dfe33eb2b3e538e8717d6578c1d08651454 (diff)
downloadu-boot-3c6050277b54f536e7effbe850dcc970a27387ab.tar.gz
u-boot-3c6050277b54f536e7effbe850dcc970a27387ab.tar.bz2
u-boot-3c6050277b54f536e7effbe850dcc970a27387ab.zip
tpm: add tpm_get_random()
Add a function to obtain random data from the TPM. Signed-off-by: André Draszik <adraszik@tycoint.com> Added commit message, add cast to min() Signed-off-by: Simon Glass <sjg@chromium.org> Acked-by: Simon Glass <sjg@chromium.org>
-rw-r--r--include/tpm.h12
-rw-r--r--lib/tpm.c43
2 files changed, 55 insertions, 0 deletions
diff --git a/include/tpm.h b/include/tpm.h
index f88388f353..2a7528dd48 100644
--- a/include/tpm.h
+++ b/include/tpm.h
@@ -651,4 +651,16 @@ uint32_t tpm_flush_specific(uint32_t key_handle, uint32_t resource_type);
uint32_t tpm_find_key_sha1(const uint8_t auth[20], const uint8_t
pubkey_digest[20], uint32_t *handle);
#endif /* CONFIG_TPM_LOAD_KEY_BY_SHA1 */
+
+/**
+ * Read random bytes from the TPM RNG. The implementation deals with the fact
+ * that the TPM may legally return fewer bytes than requested by retrying
+ * until @p count bytes have been received.
+ *
+ * @param data output buffer for the random bytes
+ * @param count size of output buffer
+ * @return return code of the operation
+ */
+uint32_t tpm_get_random(void *data, uint32_t count);
+
#endif /* __TPM_H */
diff --git a/lib/tpm.c b/lib/tpm.c
index 5659fa5e18..d21bbcfb11 100644
--- a/lib/tpm.c
+++ b/lib/tpm.c
@@ -1049,3 +1049,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;
+}