Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
torvalds
GitHub Repository: torvalds/linux
Path: blob/master/security/integrity/platform_certs/efi_parser.c
26444 views
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 ([email protected])
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
110