Commit 3c6050277b54f536e7effbe850dcc970a27387ab
Committed by
Simon Glass
1 parent
e8155dfe33
Exists in
smarc_8mq_lf_v2020.04
and in
17 other branches
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>
Showing 2 changed files with 55 additions and 0 deletions Side-by-side Diff
include/tpm.h
... | ... | @@ -651,5 +651,17 @@ |
651 | 651 | uint32_t tpm_find_key_sha1(const uint8_t auth[20], const uint8_t |
652 | 652 | pubkey_digest[20], uint32_t *handle); |
653 | 653 | #endif /* CONFIG_TPM_LOAD_KEY_BY_SHA1 */ |
654 | + | |
655 | +/** | |
656 | + * Read random bytes from the TPM RNG. The implementation deals with the fact | |
657 | + * that the TPM may legally return fewer bytes than requested by retrying | |
658 | + * until @p count bytes have been received. | |
659 | + * | |
660 | + * @param data output buffer for the random bytes | |
661 | + * @param count size of output buffer | |
662 | + * @return return code of the operation | |
663 | + */ | |
664 | +uint32_t tpm_get_random(void *data, uint32_t count); | |
665 | + | |
654 | 666 | #endif /* __TPM_H */ |
lib/tpm.c
... | ... | @@ -1049,4 +1049,47 @@ |
1049 | 1049 | #endif /* CONFIG_TPM_LOAD_KEY_BY_SHA1 */ |
1050 | 1050 | |
1051 | 1051 | #endif /* CONFIG_TPM_AUTH_SESSIONS */ |
1052 | + | |
1053 | +uint32_t tpm_get_random(void *data, uint32_t count) | |
1054 | +{ | |
1055 | + const uint8_t command[14] = { | |
1056 | + 0x0, 0xc1, /* TPM_TAG */ | |
1057 | + 0x0, 0x0, 0x0, 0xe, /* parameter size */ | |
1058 | + 0x0, 0x0, 0x0, 0x46, /* TPM_COMMAND_CODE */ | |
1059 | + }; | |
1060 | + const size_t length_offset = 10; | |
1061 | + const size_t data_size_offset = 10; | |
1062 | + const size_t data_offset = 14; | |
1063 | + uint8_t buf[COMMAND_BUFFER_SIZE], response[COMMAND_BUFFER_SIZE]; | |
1064 | + size_t response_length = sizeof(response); | |
1065 | + uint32_t data_size; | |
1066 | + uint8_t *out = data; | |
1067 | + | |
1068 | + while (count > 0) { | |
1069 | + uint32_t this_bytes = min((size_t)count, | |
1070 | + sizeof (response) - data_offset); | |
1071 | + uint32_t err; | |
1072 | + | |
1073 | + if (pack_byte_string(buf, sizeof(buf), "sd", | |
1074 | + 0, command, sizeof(command), | |
1075 | + length_offset, this_bytes)) | |
1076 | + return TPM_LIB_ERROR; | |
1077 | + err = tpm_sendrecv_command(buf, response, &response_length); | |
1078 | + if (err) | |
1079 | + return err; | |
1080 | + if (unpack_byte_string(response, response_length, "d", | |
1081 | + data_size_offset, &data_size)) | |
1082 | + return TPM_LIB_ERROR; | |
1083 | + if (data_size > count) | |
1084 | + return TPM_LIB_ERROR; | |
1085 | + if (unpack_byte_string(response, response_length, "s", | |
1086 | + data_offset, out, data_size)) | |
1087 | + return TPM_LIB_ERROR; | |
1088 | + | |
1089 | + count -= data_size; | |
1090 | + out += data_size; | |
1091 | + } | |
1092 | + | |
1093 | + return 0; | |
1094 | +} |