]> git.ipfire.org Git - people/ms/u-boot.git/blobdiff - lib/tpm.c
tpm: add missing va_end
[people/ms/u-boot.git] / lib / tpm.c
index 8a622162740f9863b76b2cddfc80dee4886c1c7a..d1cf5a8a1679fa7ab7f828c8b4290bb8aca80fe0 100644 (file)
--- a/lib/tpm.c
+++ b/lib/tpm.c
@@ -95,8 +95,10 @@ int pack_byte_string(uint8_t *str, size_t size, const char *format, ...)
                        return -1;
                }
 
-               if (offset + length > size)
+               if (offset + length > size) {
+                       va_end(args);
                        return -1;
+               }
 
                switch (*format) {
                case 'b':
@@ -163,6 +165,7 @@ 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;
                }
@@ -230,10 +233,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;
@@ -242,7 +244,7 @@ static uint32_t tpm_sendrecv_command(const void *command,
                response_length = sizeof(response_buffer);
        }
 
-       ret = uclass_first_device(UCLASS_TPM, &dev);
+       ret = uclass_first_device_err(UCLASS_TPM, &dev);
        if (ret)
                return ret;
        err = tpm_xfer(dev, command, tpm_command_size(command),
@@ -261,7 +263,7 @@ int tpm_init(void)
        int err;
        struct udevice *dev;
 
-       err = uclass_first_device(UCLASS_TPM, &dev);
+       err = uclass_first_device_err(UCLASS_TPM, &dev);
        if (err)
                return err;
        return tpm_open(dev);
@@ -645,6 +647,35 @@ uint32_t tpm_get_permissions(uint32_t index, uint32_t *perm)
        return 0;
 }
 
+#ifdef CONFIG_TPM_FLUSH_RESOURCES
+uint32_t tpm_flush_specific(uint32_t key_handle, uint32_t resource_type)
+{
+       const uint8_t command[18] = {
+               0x00, 0xc1,             /* TPM_TAG */
+               0x00, 0x00, 0x00, 0x12, /* parameter size */
+               0x00, 0x00, 0x00, 0xba, /* TPM_COMMAND_CODE */
+               0x00, 0x00, 0x00, 0x00, /* key handle */
+               0x00, 0x00, 0x00, 0x00, /* resource type */
+       };
+       const size_t key_handle_offset = 10;
+       const size_t resource_type_offset = 14;
+       uint8_t buf[COMMAND_BUFFER_SIZE], response[COMMAND_BUFFER_SIZE];
+       size_t response_length = sizeof(response);
+       uint32_t err;
+
+       if (pack_byte_string(buf, sizeof(buf), "sdd",
+                            0, command, sizeof(command),
+                            key_handle_offset, key_handle,
+                            resource_type_offset, resource_type))
+               return TPM_LIB_ERROR;
+
+       err = tpm_sendrecv_command(buf, response, &response_length);
+       if (err)
+               return err;
+       return 0;
+}
+#endif /* CONFIG_TPM_FLUSH_RESOURCES */
+
 #ifdef CONFIG_TPM_AUTH_SESSIONS
 
 /**
@@ -967,4 +998,44 @@ uint32_t tpm_get_pub_key_oiap(uint32_t key_handle, const void *usage_auth,
        return 0;
 }
 
+#ifdef CONFIG_TPM_LOAD_KEY_BY_SHA1
+uint32_t tpm_find_key_sha1(const uint8_t auth[20], const uint8_t
+                          pubkey_digest[20], uint32_t *handle)
+{
+       uint16_t key_count;
+       uint32_t key_handles[10];
+       uint8_t buf[288];
+       uint8_t *ptr;
+       uint32_t err;
+       uint8_t digest[20];
+       size_t buf_len;
+       unsigned int i;
+
+       /* fetch list of already loaded keys in the TPM */
+       err = tpm_get_capability(TPM_CAP_HANDLE, TPM_RT_KEY, buf, sizeof(buf));
+       if (err)
+               return -1;
+       key_count = get_unaligned_be16(buf);
+       ptr = buf + 2;
+       for (i = 0; i < key_count; ++i, ptr += 4)
+               key_handles[i] = get_unaligned_be32(ptr);
+
+       /* now search a(/ the) key which we can access with the given auth */
+       for (i = 0; i < key_count; ++i) {
+               buf_len = sizeof(buf);
+               err = tpm_get_pub_key_oiap(key_handles[i], auth, buf, &buf_len);
+               if (err && err != TPM_AUTHFAIL)
+                       return -1;
+               if (err)
+                       continue;
+               sha1_csum(buf, buf_len, digest);
+               if (!memcmp(digest, pubkey_digest, 20)) {
+                       *handle = key_handles[i];
+                       return 0;
+               }
+       }
+       return 1;
+}
+#endif /* CONFIG_TPM_LOAD_KEY_BY_SHA1 */
+
 #endif /* CONFIG_TPM_AUTH_SESSIONS */