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