Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0+
0002 /* EFI signature/key/certificate list parser
0003  *
0004  * Copyright (C) 2012, 2016 Red Hat, Inc. All Rights Reserved.
0005  * Written by David Howells (dhowells@redhat.com)
0006  */
0007 
0008 #define pr_fmt(fmt) "EFI: "fmt
0009 #include <linux/module.h>
0010 #include <linux/printk.h>
0011 #include <linux/err.h>
0012 #include <linux/efi.h>
0013 
0014 /**
0015  * parse_efi_signature_list - Parse an EFI signature list for certificates
0016  * @source: The source of the key
0017  * @data: The data blob to parse
0018  * @size: The size of the data blob
0019  * @get_handler_for_guid: Get the handler func for the sig type (or NULL)
0020  *
0021  * Parse an EFI signature list looking for elements of interest.  A list is
0022  * made up of a series of sublists, where all the elements in a sublist are of
0023  * the same type, but sublists can be of different types.
0024  *
0025  * For each sublist encountered, the @get_handler_for_guid function is called
0026  * with the type specifier GUID and returns either a pointer to a function to
0027  * handle elements of that type or NULL if the type is not of interest.
0028  *
0029  * If the sublist is of interest, each element is passed to the handler
0030  * function in turn.
0031  *
0032  * Error EBADMSG is returned if the list doesn't parse correctly and 0 is
0033  * returned if the list was parsed correctly.  No error can be returned from
0034  * the @get_handler_for_guid function or the element handler function it
0035  * returns.
0036  */
0037 int __init parse_efi_signature_list(
0038     const char *source,
0039     const void *data, size_t size,
0040     efi_element_handler_t (*get_handler_for_guid)(const efi_guid_t *))
0041 {
0042     efi_element_handler_t handler;
0043     unsigned int offs = 0;
0044 
0045     pr_devel("-->%s(,%zu)\n", __func__, size);
0046 
0047     while (size > 0) {
0048         const efi_signature_data_t *elem;
0049         efi_signature_list_t list;
0050         size_t lsize, esize, hsize, elsize;
0051 
0052         if (size < sizeof(list))
0053             return -EBADMSG;
0054 
0055         memcpy(&list, data, sizeof(list));
0056         pr_devel("LIST[%04x] guid=%pUl ls=%x hs=%x ss=%x\n",
0057              offs,
0058              &list.signature_type, list.signature_list_size,
0059              list.signature_header_size, list.signature_size);
0060 
0061         lsize = list.signature_list_size;
0062         hsize = list.signature_header_size;
0063         esize = list.signature_size;
0064         elsize = lsize - sizeof(list) - hsize;
0065 
0066         if (lsize > size) {
0067             pr_devel("<--%s() = -EBADMSG [overrun @%x]\n",
0068                  __func__, offs);
0069             return -EBADMSG;
0070         }
0071 
0072         if (lsize < sizeof(list) ||
0073             lsize - sizeof(list) < hsize ||
0074             esize < sizeof(*elem) ||
0075             elsize < esize ||
0076             elsize % esize != 0) {
0077             pr_devel("- bad size combo @%x\n", offs);
0078             return -EBADMSG;
0079         }
0080 
0081         handler = get_handler_for_guid(&list.signature_type);
0082         if (!handler) {
0083             data += lsize;
0084             size -= lsize;
0085             offs += lsize;
0086             continue;
0087         }
0088 
0089         data += sizeof(list) + hsize;
0090         size -= sizeof(list) + hsize;
0091         offs += sizeof(list) + hsize;
0092 
0093         for (; elsize > 0; elsize -= esize) {
0094             elem = data;
0095 
0096             pr_devel("ELEM[%04x]\n", offs);
0097             handler(source,
0098                 &elem->signature_data,
0099                 esize - sizeof(*elem));
0100 
0101             data += esize;
0102             size -= esize;
0103             offs += esize;
0104         }
0105     }
0106 
0107     return 0;
0108 }