efi_parser.c 2.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108
  1. // SPDX-License-Identifier: GPL-2.0+
  2. /* EFI signature/key/certificate list parser
  3. *
  4. * Copyright (C) 2012, 2016 Red Hat, Inc. All Rights Reserved.
  5. * Written by David Howells (dhowells@redhat.com)
  6. */
  7. #define pr_fmt(fmt) "EFI: "fmt
  8. #include <linux/module.h>
  9. #include <linux/printk.h>
  10. #include <linux/err.h>
  11. #include <linux/efi.h>
  12. /**
  13. * parse_efi_signature_list - Parse an EFI signature list for certificates
  14. * @source: The source of the key
  15. * @data: The data blob to parse
  16. * @size: The size of the data blob
  17. * @get_handler_for_guid: Get the handler func for the sig type (or NULL)
  18. *
  19. * Parse an EFI signature list looking for elements of interest. A list is
  20. * made up of a series of sublists, where all the elements in a sublist are of
  21. * the same type, but sublists can be of different types.
  22. *
  23. * For each sublist encountered, the @get_handler_for_guid function is called
  24. * with the type specifier GUID and returns either a pointer to a function to
  25. * handle elements of that type or NULL if the type is not of interest.
  26. *
  27. * If the sublist is of interest, each element is passed to the handler
  28. * function in turn.
  29. *
  30. * Error EBADMSG is returned if the list doesn't parse correctly and 0 is
  31. * returned if the list was parsed correctly. No error can be returned from
  32. * the @get_handler_for_guid function or the element handler function it
  33. * returns.
  34. */
  35. int __init parse_efi_signature_list(
  36. const char *source,
  37. const void *data, size_t size,
  38. efi_element_handler_t (*get_handler_for_guid)(const efi_guid_t *))
  39. {
  40. efi_element_handler_t handler;
  41. unsigned int offs = 0;
  42. pr_devel("-->%s(,%zu)\n", __func__, size);
  43. while (size > 0) {
  44. const efi_signature_data_t *elem;
  45. efi_signature_list_t list;
  46. size_t lsize, esize, hsize, elsize;
  47. if (size < sizeof(list))
  48. return -EBADMSG;
  49. memcpy(&list, data, sizeof(list));
  50. pr_devel("LIST[%04x] guid=%pUl ls=%x hs=%x ss=%x\n",
  51. offs,
  52. &list.signature_type, list.signature_list_size,
  53. list.signature_header_size, list.signature_size);
  54. lsize = list.signature_list_size;
  55. hsize = list.signature_header_size;
  56. esize = list.signature_size;
  57. elsize = lsize - sizeof(list) - hsize;
  58. if (lsize > size) {
  59. pr_devel("<--%s() = -EBADMSG [overrun @%x]\n",
  60. __func__, offs);
  61. return -EBADMSG;
  62. }
  63. if (lsize < sizeof(list) ||
  64. lsize - sizeof(list) < hsize ||
  65. esize < sizeof(*elem) ||
  66. elsize < esize ||
  67. elsize % esize != 0) {
  68. pr_devel("- bad size combo @%x\n", offs);
  69. return -EBADMSG;
  70. }
  71. handler = get_handler_for_guid(&list.signature_type);
  72. if (!handler) {
  73. data += lsize;
  74. size -= lsize;
  75. offs += lsize;
  76. continue;
  77. }
  78. data += sizeof(list) + hsize;
  79. size -= sizeof(list) + hsize;
  80. offs += sizeof(list) + hsize;
  81. for (; elsize > 0; elsize -= esize) {
  82. elem = data;
  83. pr_devel("ELEM[%04x]\n", offs);
  84. handler(source,
  85. &elem->signature_data,
  86. esize - sizeof(*elem));
  87. data += esize;
  88. size -= esize;
  89. offs += esize;
  90. }
  91. }
  92. return 0;
  93. }