cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

efi_parser.c (2991B)


      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 */
     37int __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}