Path: blob/master/security/integrity/platform_certs/efi_parser.c
26444 views
// SPDX-License-Identifier: GPL-2.0+1/* EFI signature/key/certificate list parser2*3* Copyright (C) 2012, 2016 Red Hat, Inc. All Rights Reserved.4* Written by David Howells ([email protected])5*/67#define pr_fmt(fmt) "EFI: "fmt8#include <linux/module.h>9#include <linux/printk.h>10#include <linux/err.h>11#include <linux/efi.h>1213/**14* parse_efi_signature_list - Parse an EFI signature list for certificates15* @source: The source of the key16* @data: The data blob to parse17* @size: The size of the data blob18* @get_handler_for_guid: Get the handler func for the sig type (or NULL)19*20* Parse an EFI signature list looking for elements of interest. A list is21* made up of a series of sublists, where all the elements in a sublist are of22* the same type, but sublists can be of different types.23*24* For each sublist encountered, the @get_handler_for_guid function is called25* with the type specifier GUID and returns either a pointer to a function to26* handle elements of that type or NULL if the type is not of interest.27*28* If the sublist is of interest, each element is passed to the handler29* function in turn.30*31* Error EBADMSG is returned if the list doesn't parse correctly and 0 is32* returned if the list was parsed correctly. No error can be returned from33* the @get_handler_for_guid function or the element handler function it34* returns.35*/36int __init parse_efi_signature_list(37const char *source,38const void *data, size_t size,39efi_element_handler_t (*get_handler_for_guid)(const efi_guid_t *))40{41efi_element_handler_t handler;42unsigned int offs = 0;4344pr_devel("-->%s(,%zu)\n", __func__, size);4546while (size > 0) {47const efi_signature_data_t *elem;48efi_signature_list_t list;49size_t lsize, esize, hsize, elsize;5051if (size < sizeof(list))52return -EBADMSG;5354memcpy(&list, data, sizeof(list));55pr_devel("LIST[%04x] guid=%pUl ls=%x hs=%x ss=%x\n",56offs,57&list.signature_type, list.signature_list_size,58list.signature_header_size, list.signature_size);5960lsize = list.signature_list_size;61hsize = list.signature_header_size;62esize = list.signature_size;63elsize = lsize - sizeof(list) - hsize;6465if (lsize > size) {66pr_devel("<--%s() = -EBADMSG [overrun @%x]\n",67__func__, offs);68return -EBADMSG;69}7071if (lsize < sizeof(list) ||72lsize - sizeof(list) < hsize ||73esize < sizeof(*elem) ||74elsize < esize ||75elsize % esize != 0) {76pr_devel("- bad size combo @%x\n", offs);77return -EBADMSG;78}7980handler = get_handler_for_guid(&list.signature_type);81if (!handler) {82data += lsize;83size -= lsize;84offs += lsize;85continue;86}8788data += sizeof(list) + hsize;89size -= sizeof(list) + hsize;90offs += sizeof(list) + hsize;9192for (; elsize > 0; elsize -= esize) {93elem = data;9495pr_devel("ELEM[%04x]\n", offs);96handler(source,97&elem->signature_data,98esize - sizeof(*elem));99100data += esize;101size -= esize;102offs += esize;103}104}105106return 0;107}108109110