summaryrefslogtreecommitdiff
path: root/lib/configtable.c
blob: 66e97f63fc0ba436ded5c6a9161546f0387f5dae (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
// SPDX-License-Identifier: BSD-2-Clause-Patent
/*
 * Copyright 2013 <James.Bottomley@HansenPartnership.com>
 *
 * read some platform configuration tables
 */
#include "shim.h"

void *
configtable_get_table(EFI_GUID *guid)
{
	unsigned int i;

	for (i = 0; i < ST->NumberOfTableEntries; i++) {
		EFI_CONFIGURATION_TABLE *CT = &ST->ConfigurationTable[i];

		if (CompareGuid(guid, &CT->VendorGuid) == 0) {
			return CT->VendorTable;
		}
	}
	return NULL;
}

EFI_IMAGE_EXECUTION_INFO_TABLE *
configtable_get_image_table(void)
{
	return configtable_get_table(&SIG_DB);
}

EFI_IMAGE_EXECUTION_INFO *
configtable_find_image(const EFI_DEVICE_PATH *DevicePath)
{
	EFI_IMAGE_EXECUTION_INFO_TABLE *t = configtable_get_image_table();

	if (!t)
		return NULL;

	int entries = t->NumberOfImages;
	EFI_IMAGE_EXECUTION_INFO *e = t->InformationInfo;

	int i;
	for (i = 0; i < entries; i++) {
#ifdef DEBUG_CONFIG
		console_print(L"InfoSize = %d  Action = %d\n", e->InfoSize, e->Action);

		/* print what we have for debugging */
		UINT8 *d = (UINT8 *)e; // + sizeof(UINT32)*2;
		console_print(L"Data: %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x\n",
		      d[0], d[1], d[2], d[3], d[4], d[5], d[6], d[7], d[8], d[9], d[10], d[11], d[12], d[13], d[14], d[15]);
		d += 16;
		console_print(L"Data: %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x\n",
		      d[0], d[1], d[2], d[3], d[4], d[5], d[6], d[7], d[8], d[9], d[10], d[11], d[12], d[13], d[14], d[15]);
		d += 16;
		console_print(L"Data: %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x\n",
		      d[0], d[1], d[2], d[3], d[4], d[5], d[6], d[7], d[8], d[9], d[10], d[11], d[12], d[13], d[14], d[15]);
		d += 16;
		console_print(L"Data: %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x\n",
		      d[0], d[1], d[2], d[3], d[4], d[5], d[6], d[7], d[8], d[9], d[10], d[11], d[12], d[13], d[14], d[15]);
		d += 16;
		console_print(L"Data: %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x\n",
		      d[0], d[1], d[2], d[3], d[4], d[5], d[6], d[7], d[8], d[9], d[10], d[11], d[12], d[13], d[14], d[15]);
		d += 16;
		console_print(L"Data: %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x\n",
		      d[0], d[1], d[2], d[3], d[4], d[5], d[6], d[7], d[8], d[9], d[10], d[11], d[12], d[13], d[14], d[15]);
#endif
		CHAR16 *name = (CHAR16 *)(e->Data);
		int skip = 0;

		/* There's a bug in a lot of EFI platforms and they forget to
		 * put the name here.  The only real way of detecting it is to
		 * look for either a UC16 NULL or ASCII as UC16 */
		if (name[0] == '\0' || (e->Data[1] == 0 && e->Data[3] == 0)) {
			skip = StrSize(name);
#ifdef DEBUG_CONFIG
			console_print(L"FOUND NAME %s (%d)\n", name, skip);
#endif
		}
		EFI_DEVICE_PATH *dp = (EFI_DEVICE_PATH *)(e->Data + skip), *dpn = dp;
		if (dp->Type == 0 || dp->Type > 6 || dp->SubType == 0
		    || ((unsigned)((dp->Length[1] << 8) + dp->Length[0]) > e->InfoSize)) {
			/* Parse error, table corrupt, bail */
			console_print(L"Image Execution Information table corrupt\n");
			break;
		}

		UINTN Size;
		DevicePathInstance(&dpn, &Size);
#ifdef DEBUG_CONFIG
		console_print(L"Path: %s\n", DevicePathToStr(dp));
		console_print(L"Device Path Size %d\n", Size);
#endif
		if (Size > e->InfoSize) {
			/* parse error; the platform obviously has a
			 * corrupted image table; bail */
			console_print(L"Image Execution Information table corrupt\n");
			break;
		}

		if (CompareMem(dp, (void *)DevicePath, Size) == 0) {
#ifdef DEBUG_CONFIG
			console_print(L"***FOUND\n");
			console_get_keystroke();
#endif
			return e;
		}
		e = (EFI_IMAGE_EXECUTION_INFO *)((UINT8 *)e + e->InfoSize);
	}

#ifdef DEBUG_CONFIG
	console_print(L"***NOT FOUND\n");
	console_get_keystroke();
#endif

	return NULL;
}

int
configtable_image_is_forbidden(const EFI_DEVICE_PATH *DevicePath)
{
	EFI_IMAGE_EXECUTION_INFO *e = configtable_find_image(DevicePath);

	/* Image may not be in DB if it gets executed successfully If it is,
	 * and EFI_IMAGE_EXECUTION_INITIALIZED is not set, then the image
	 * isn't authenticated.  If there's no signature, usually
	 * EFI_IMAGE_EXECUTION_AUTH_UNTESTED is set, if the hash is in dbx,
	 * EFI_IMAGE_EXECUTION_AUTH_SIG_FOUND is returned, and if the key is
	 * in dbx, EFI_IMAGE_EXECUTION_AUTH_SIG_FAILED is returned*/

	if (e && (e->Action == EFI_IMAGE_EXECUTION_AUTH_SIG_FOUND
		  || e->Action == EFI_IMAGE_EXECUTION_AUTH_SIG_FAILED)) {
		/* this means the images signing key is in dbx */
#ifdef DEBUG_CONFIG
		console_print(L"SIGNATURE IS IN DBX, FORBIDDING EXECUTION\n");
#endif
		return 1;
	}

	return 0;
}