]> git.proxmox.com Git - efi-boot-shim.git/blame - shim.c
Cryptlib: Update to the latest edk2 commit
[efi-boot-shim.git] / shim.c
CommitLineData
f898777d
MG
1/*
2 * shim - trivial UEFI first-stage bootloader
3 *
4 * Copyright 2012 Red Hat, Inc <mjg@redhat.com>
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 *
10 * Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 *
13 * Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the
16 * distribution.
17 *
18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
20 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
21 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
22 * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
23 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
24 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
25 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
27 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
29 * OF THE POSSIBILITY OF SUCH DAMAGE.
30 *
31 * Significant portions of this code are derived from Tianocore
32 * (http://tianocore.sf.net) and are Copyright 2009-2012 Intel
33 * Corporation.
34 */
35
b2fe1780
MG
36#include <efi.h>
37#include <efilib.h>
7f055335 38#include <Library/BaseCryptLib.h>
b2fe1780 39#include "PeImage.h"
f4b24734 40#include "shim.h"
d8e330b9 41#include "netboot.h"
3d79bcb2 42#include "httpboot.h"
6d50f87a 43#include "shim_cert.h"
39df41ce 44#include "replacements.h"
22b58f24 45#include "tpm.h"
2cead91e 46#include "ucs2.h"
b2fe1780 47
79424b09 48#include "guid.h"
7d602e84 49#include "variables.h"
79424b09 50#include "efiauthenticated.h"
3508c40c 51#include "security_policy.h"
09a37bbc 52#include "console.h"
fc986307 53#include "version.h"
79424b09 54
6c180c60
MTL
55#include <stdarg.h>
56#include <openssl/x509.h>
57#include <openssl/x509v3.h>
58
6f040920
PJ
59#define FALLBACK L"\\fb" EFI_ARCH L".efi"
60#define MOK_MANAGER L"\\mm" EFI_ARCH L".efi"
f898777d 61
6c180c60
MTL
62#define OID_EKU_MODSIGN "1.3.6.1.4.1.2312.16.1.2"
63
7f055335 64static EFI_SYSTEM_TABLE *systab;
29f3c91d 65static EFI_HANDLE global_image_handle;
7f055335
MG
66static EFI_STATUS (EFIAPI *entry_point) (EFI_HANDLE image_handle, EFI_SYSTEM_TABLE *system_table);
67
14d4b8e5
GCPL
68static CHAR16 *second_stage;
69static void *load_options;
70static UINT32 load_options_size;
4bfb13d8
GCPL
71static UINT8 in_protocol;
72
73#define perror(fmt, ...) ({ \
74 UINTN __perror_ret = 0; \
eb72a4c3 75 if (!in_protocol) \
4bfb13d8
GCPL
76 __perror_ret = Print((fmt), ##__VA_ARGS__); \
77 __perror_ret; \
78 })
14d4b8e5 79
29015069
PJ
80EFI_GUID SHIM_LOCK_GUID = { 0x605dab50, 0xe046, 0x4300, {0xab, 0xb6, 0x3d, 0xd8, 0x10, 0xdd, 0x8b, 0x23} };
81
f898777d
MG
82/*
83 * The vendor certificate used for validating the second stage loader
84 */
02388bcd
PJ
85extern struct {
86 UINT32 vendor_cert_size;
87 UINT32 vendor_dbx_size;
88 UINT32 vendor_cert_offset;
89 UINT32 vendor_dbx_offset;
90} cert_table;
91
92UINT32 vendor_cert_size;
93UINT32 vendor_dbx_size;
94UINT8 *vendor_cert;
95UINT8 *vendor_dbx;
b2fe1780 96
39df41ce
PJ
97/*
98 * indicator of how an image has been verified
99 */
100verification_method_t verification_method;
101int loader_is_participating;
102
96b0c2f9
MG
103#define EFI_IMAGE_SECURITY_DATABASE_GUID { 0xd719b2cb, 0x3d3a, 0x4596, { 0xa3, 0xbc, 0xda, 0xd0, 0x0e, 0x67, 0x65, 0x6f }}
104
d95b24bd 105UINT8 user_insecure_mode;
ef0383d0 106UINT8 ignore_db;
7127b1ab 107
1a109376
MG
108typedef enum {
109 DATA_FOUND,
110 DATA_NOT_FOUND,
111 VAR_NOT_FOUND
112} CHECK_STATUS;
113
28c58133
GCPL
114typedef struct {
115 UINT32 MokSize;
116 UINT8 *Mok;
117} MokListNode;
118
f898777d
MG
119/*
120 * Perform basic bounds checking of the intra-image pointers
121 */
5495694c 122static void *ImageAddress (void *image, unsigned int size, unsigned int address)
b2fe1780 123{
f898777d
MG
124 if (address > size)
125 return NULL;
9d56c38f 126
f898777d
MG
127 return image + address;
128}
9d56c38f 129
750584c2
PJ
130/* here's a chart:
131 * i686 x86_64 aarch64
132 * 64-on-64: nyet yes yes
133 * 64-on-32: nyet yes nyet
134 * 32-on-32: yes yes no
135 */
136static int
137allow_64_bit(void)
138{
139#if defined(__x86_64__) || defined(__aarch64__)
140 return 1;
141#elif defined(__i386__) || defined(__i686__)
142 /* Right now blindly assuming the kernel will correctly detect this
143 * and /halt the system/ if you're not really on a 64-bit cpu */
144 if (in_protocol)
145 return 1;
146 return 0;
147#else /* assuming everything else is 32-bit... */
148 return 0;
149#endif
150}
151
152static int
153allow_32_bit(void)
154{
155#if defined(__x86_64__)
156#if defined(ALLOW_32BIT_KERNEL_ON_X64)
157 if (in_protocol)
158 return 1;
159 return 0;
160#else
161 return 0;
162#endif
163#elif defined(__i386__) || defined(__i686__)
164 return 1;
165#elif defined(__arch64__)
166 return 0;
167#else /* assuming everything else is 32-bit... */
168 return 1;
169#endif
170}
171
172static int
173image_is_64_bit(EFI_IMAGE_OPTIONAL_HEADER_UNION *PEHdr)
174{
175 /* .Magic is the same offset in all cases */
176 if (PEHdr->Pe32Plus.OptionalHeader.Magic
177 == EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC)
178 return 1;
179 return 0;
180}
181
182static const UINT16 machine_type =
183#if defined(__x86_64__)
184 IMAGE_FILE_MACHINE_X64;
185#elif defined(__aarch64__)
186 IMAGE_FILE_MACHINE_ARM64;
187#elif defined(__arm__)
188 IMAGE_FILE_MACHINE_ARMTHUMB_MIXED;
189#elif defined(__i386__) || defined(__i486__) || defined(__i686__)
190 IMAGE_FILE_MACHINE_I386;
191#elif defined(__ia64__)
192 IMAGE_FILE_MACHINE_IA64;
193#else
194#error this architecture is not supported by shim
195#endif
196
197static int
198image_is_loadable(EFI_IMAGE_OPTIONAL_HEADER_UNION *PEHdr)
199{
200 /* If the machine type doesn't match the binary, bail, unless
201 * we're in an allowed 64-on-32 scenario */
202 if (PEHdr->Pe32.FileHeader.Machine != machine_type) {
203 if (!(machine_type == IMAGE_FILE_MACHINE_I386 &&
204 PEHdr->Pe32.FileHeader.Machine == IMAGE_FILE_MACHINE_X64 &&
205 allow_64_bit())) {
206 return 0;
207 }
208 }
209
210 /* If it's not a header type we recognize at all, bail */
211 switch (PEHdr->Pe32Plus.OptionalHeader.Magic) {
212 case EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC:
213 case EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC:
214 break;
215 default:
216 return 0;
217 }
218
219 /* and now just check for general 64-vs-32 compatibility */
220 if (image_is_64_bit(PEHdr)) {
221 if (allow_64_bit())
222 return 1;
223 } else {
224 if (allow_32_bit())
225 return 1;
226 }
227 return 0;
228}
229
f898777d
MG
230/*
231 * Perform the actual relocation
232 */
7db60bd8 233static EFI_STATUS relocate_coff (PE_COFF_LOADER_IMAGE_CONTEXT *context,
a846aedd 234 EFI_IMAGE_SECTION_HEADER *Section,
a7249a65 235 void *orig, void *data)
f898777d
MG
236{
237 EFI_IMAGE_BASE_RELOCATION *RelocBase, *RelocBaseEnd;
238 UINT64 Adjust;
239 UINT16 *Reloc, *RelocEnd;
240 char *Fixup, *FixupBase, *FixupData = NULL;
241 UINT16 *Fixup16;
242 UINT32 *Fixup32;
243 UINT64 *Fixup64;
244 int size = context->ImageSize;
a7249a65 245 void *ImageEnd = (char *)orig + size;
a846aedd 246 int n = 0;
9d56c38f 247
750584c2
PJ
248 if (image_is_64_bit(context->PEHdr))
249 context->PEHdr->Pe32Plus.OptionalHeader.ImageBase = (UINT64)(unsigned long)data;
250 else
251 context->PEHdr->Pe32.OptionalHeader.ImageBase = (UINT32)(unsigned long)data;
7f055335 252
a846aedd
PJ
253 /* Alright, so here's how this works:
254 *
255 * context->RelocDir gives us two things:
256 * - the VA the table of base relocation blocks are (maybe) to be
257 * mapped at (RelocDir->VirtualAddress)
258 * - the virtual size (RelocDir->Size)
259 *
260 * The .reloc section (Section here) gives us some other things:
261 * - the name! kind of. (Section->Name)
262 * - the virtual size (Section->VirtualSize), which should be the same
263 * as RelocDir->Size
264 * - the virtual address (Section->VirtualAddress)
265 * - the file section size (Section->SizeOfRawData), which is
266 * a multiple of OptHdr->FileAlignment. Only useful for image
267 * validation, not really useful for iteration bounds.
268 * - the file address (Section->PointerToRawData)
269 * - a bunch of stuff we don't use that's 0 in our binaries usually
270 * - Flags (Section->Characteristics)
271 *
272 * and then the thing that's actually at the file address is an array
273 * of EFI_IMAGE_BASE_RELOCATION structs with some values packed behind
274 * them. The SizeOfBlock field of this structure includes the
275 * structure itself, and adding it to that structure's address will
276 * yield the next entry in the array.
277 */
278 RelocBase = ImageAddress(orig, size, Section->PointerToRawData);
279 /* RelocBaseEnd here is the address of the first entry /past/ the
280 * table. */
281 RelocBaseEnd = ImageAddress(orig, size, Section->PointerToRawData +
282 Section->Misc.VirtualSize);
283
284 if (!RelocBase && !RelocBaseEnd)
285 return EFI_SUCCESS;
9d56c38f 286
f898777d 287 if (!RelocBase || !RelocBaseEnd) {
4bfb13d8 288 perror(L"Reloc table overflows binary\n");
f898777d 289 return EFI_UNSUPPORTED;
9d56c38f
MG
290 }
291
8e9d3af7 292 Adjust = (UINTN)data - context->ImageAddress;
9d56c38f 293
8c46e07f
PJ
294 if (Adjust == 0)
295 return EFI_SUCCESS;
296
f898777d
MG
297 while (RelocBase < RelocBaseEnd) {
298 Reloc = (UINT16 *) ((char *) RelocBase + sizeof (EFI_IMAGE_BASE_RELOCATION));
9d56c38f 299
8c46e07f 300 if ((RelocBase->SizeOfBlock == 0) || (RelocBase->SizeOfBlock > context->RelocDir->Size)) {
a846aedd 301 perror(L"Reloc %d block size %d is invalid\n", n, RelocBase->SizeOfBlock);
8c46e07f
PJ
302 return EFI_UNSUPPORTED;
303 }
304
305 RelocEnd = (UINT16 *) ((char *) RelocBase + RelocBase->SizeOfBlock);
a7249a65 306 if ((void *)RelocEnd < orig || (void *)RelocEnd > ImageEnd) {
a846aedd 307 perror(L"Reloc %d entry overflows binary\n", n);
f898777d 308 return EFI_UNSUPPORTED;
9d56c38f
MG
309 }
310
7db60bd8 311 FixupBase = ImageAddress(data, size, RelocBase->VirtualAddress);
f898777d 312 if (!FixupBase) {
a846aedd 313 perror(L"Reloc %d Invalid fixupbase\n", n);
f898777d 314 return EFI_UNSUPPORTED;
9d56c38f 315 }
9d56c38f 316
f898777d
MG
317 while (Reloc < RelocEnd) {
318 Fixup = FixupBase + (*Reloc & 0xFFF);
319 switch ((*Reloc) >> 12) {
320 case EFI_IMAGE_REL_BASED_ABSOLUTE:
321 break;
9d56c38f 322
f898777d
MG
323 case EFI_IMAGE_REL_BASED_HIGH:
324 Fixup16 = (UINT16 *) Fixup;
325 *Fixup16 = (UINT16) (*Fixup16 + ((UINT16) ((UINT32) Adjust >> 16)));
326 if (FixupData != NULL) {
327 *(UINT16 *) FixupData = *Fixup16;
328 FixupData = FixupData + sizeof (UINT16);
329 }
330 break;
9d56c38f 331
f898777d
MG
332 case EFI_IMAGE_REL_BASED_LOW:
333 Fixup16 = (UINT16 *) Fixup;
334 *Fixup16 = (UINT16) (*Fixup16 + (UINT16) Adjust);
335 if (FixupData != NULL) {
336 *(UINT16 *) FixupData = *Fixup16;
337 FixupData = FixupData + sizeof (UINT16);
338 }
339 break;
b2fe1780 340
f898777d
MG
341 case EFI_IMAGE_REL_BASED_HIGHLOW:
342 Fixup32 = (UINT32 *) Fixup;
343 *Fixup32 = *Fixup32 + (UINT32) Adjust;
344 if (FixupData != NULL) {
345 FixupData = ALIGN_POINTER (FixupData, sizeof (UINT32));
346 *(UINT32 *)FixupData = *Fixup32;
347 FixupData = FixupData + sizeof (UINT32);
348 }
349 break;
b2fe1780 350
f898777d
MG
351 case EFI_IMAGE_REL_BASED_DIR64:
352 Fixup64 = (UINT64 *) Fixup;
353 *Fixup64 = *Fixup64 + (UINT64) Adjust;
354 if (FixupData != NULL) {
355 FixupData = ALIGN_POINTER (FixupData, sizeof(UINT64));
356 *(UINT64 *)(FixupData) = *Fixup64;
357 FixupData = FixupData + sizeof(UINT64);
358 }
359 break;
b2fe1780 360
f898777d 361 default:
a846aedd 362 perror(L"Reloc %d Unknown relocation\n", n);
f898777d
MG
363 return EFI_UNSUPPORTED;
364 }
365 Reloc += 1;
0e6b0195 366 }
f898777d 367 RelocBase = (EFI_IMAGE_BASE_RELOCATION *) RelocEnd;
a846aedd 368 n++;
7f055335 369 }
b2fe1780
MG
370
371 return EFI_SUCCESS;
372}
373
5f18e2e3
GCPL
374static BOOLEAN verify_x509(UINT8 *Cert, UINTN CertSize)
375{
376 UINTN length;
377
378 if (!Cert || CertSize < 4)
379 return FALSE;
380
381 /*
382 * A DER encoding x509 certificate starts with SEQUENCE(0x30),
383 * the number of length bytes, and the number of value bytes.
384 * The size of a x509 certificate is usually between 127 bytes
385 * and 64KB. For convenience, assume the number of value bytes
386 * is 2, i.e. the second byte is 0x82.
387 */
388 if (Cert[0] != 0x30 || Cert[1] != 0x82)
389 return FALSE;
390
391 length = Cert[2]<<8 | Cert[3];
392 if (length != (CertSize - 4))
393 return FALSE;
394
395 return TRUE;
396}
397
6c180c60
MTL
398static BOOLEAN verify_eku(UINT8 *Cert, UINTN CertSize)
399{
400 X509 *x509;
401 CONST UINT8 *Temp = Cert;
402 EXTENDED_KEY_USAGE *eku;
403 ASN1_OBJECT *module_signing;
404
405 module_signing = OBJ_nid2obj(OBJ_create(OID_EKU_MODSIGN, NULL, NULL));
406
407 x509 = d2i_X509 (NULL, &Temp, (long) CertSize);
408 if (x509 != NULL) {
409 eku = X509_get_ext_d2i(x509, NID_ext_key_usage, NULL, NULL);
410
411 if (eku) {
412 int i = 0;
413 for (i = 0; i < sk_ASN1_OBJECT_num(eku); i++) {
414 ASN1_OBJECT *key_usage = sk_ASN1_OBJECT_value(eku, i);
415
416 if (OBJ_cmp(module_signing, key_usage) == 0)
417 return FALSE;
418 }
419 EXTENDED_KEY_USAGE_free(eku);
420 }
421
422 X509_free(x509);
423 }
424
425 OBJ_cleanup();
426
427 return TRUE;
428}
429
e0b78774
PJ
430static CHECK_STATUS check_db_cert_in_ram(EFI_SIGNATURE_LIST *CertList,
431 UINTN dbsize,
432 WIN_CERTIFICATE_EFI_PKCS *data,
433 UINT8 *hash)
019b0c5c 434{
019b0c5c 435 EFI_SIGNATURE_DATA *Cert;
5f18e2e3 436 UINTN CertSize;
96b0c2f9 437 BOOLEAN IsFound = FALSE;
79424b09 438 EFI_GUID CertType = X509_GUID;
1a109376 439
1a109376 440 while ((dbsize > 0) && (dbsize >= CertList->SignatureListSize)) {
96b0c2f9 441 if (CompareGuid (&CertList->SignatureType, &CertType) == 0) {
1a109376 442 Cert = (EFI_SIGNATURE_DATA *) ((UINT8 *) CertList + sizeof (EFI_SIGNATURE_LIST) + CertList->SignatureHeaderSize);
5f18e2e3
GCPL
443 CertSize = CertList->SignatureSize - sizeof(EFI_GUID);
444 if (verify_x509(Cert->SignatureData, CertSize)) {
6c180c60
MTL
445 if (verify_eku(Cert->SignatureData, CertSize)) {
446 IsFound = AuthenticodeVerify (data->CertData,
447 data->Hdr.dwLength - sizeof(data->Hdr),
448 Cert->SignatureData,
449 CertSize,
450 hash, SHA256_DIGEST_SIZE);
451 if (IsFound)
452 return DATA_FOUND;
453 }
5f18e2e3
GCPL
454 } else if (verbose) {
455 console_notify(L"Not a DER encoding x.509 Certificate");
1a109376 456 }
1a109376
MG
457 }
458
459 dbsize -= CertList->SignatureListSize;
460 CertList = (EFI_SIGNATURE_LIST *) ((UINT8 *) CertList + CertList->SignatureListSize);
461 }
462
1a109376
MG
463 return DATA_NOT_FOUND;
464}
465
e0b78774
PJ
466static CHECK_STATUS check_db_cert(CHAR16 *dbname, EFI_GUID guid,
467 WIN_CERTIFICATE_EFI_PKCS *data, UINT8 *hash)
1a109376 468{
e0b78774 469 CHECK_STATUS rc;
1a109376 470 EFI_STATUS efi_status;
1a109376 471 EFI_SIGNATURE_LIST *CertList;
1a109376 472 UINTN dbsize = 0;
7d602e84 473 UINT8 *db;
019b0c5c 474
7d602e84 475 efi_status = get_variable(dbname, &db, &dbsize, guid);
019b0c5c 476
e0b78774 477 if (efi_status != EFI_SUCCESS)
1a109376 478 return VAR_NOT_FOUND;
019b0c5c 479
7d602e84 480 CertList = (EFI_SIGNATURE_LIST *)db;
019b0c5c 481
e0b78774
PJ
482 rc = check_db_cert_in_ram(CertList, dbsize, data, hash);
483
484 FreePool(db);
485
486 return rc;
487}
488
0aee67a8
MG
489/*
490 * Check a hash against an EFI_SIGNATURE_LIST in a buffer
491 */
e0b78774
PJ
492static CHECK_STATUS check_db_hash_in_ram(EFI_SIGNATURE_LIST *CertList,
493 UINTN dbsize, UINT8 *data,
494 int SignatureSize, EFI_GUID CertType)
495{
496 EFI_SIGNATURE_DATA *Cert;
497 UINTN CertCount, Index;
498 BOOLEAN IsFound = FALSE;
499
1a109376 500 while ((dbsize > 0) && (dbsize >= CertList->SignatureListSize)) {
19e4fc29 501 CertCount = (CertList->SignatureListSize -sizeof (EFI_SIGNATURE_LIST) - CertList->SignatureHeaderSize) / CertList->SignatureSize;
019b0c5c 502 Cert = (EFI_SIGNATURE_DATA *) ((UINT8 *) CertList + sizeof (EFI_SIGNATURE_LIST) + CertList->SignatureHeaderSize);
96b0c2f9 503 if (CompareGuid(&CertList->SignatureType, &CertType) == 0) {
019b0c5c 504 for (Index = 0; Index < CertCount; Index++) {
1a109376 505 if (CompareMem (Cert->SignatureData, data, SignatureSize) == 0) {
019b0c5c
MG
506 //
507 // Find the signature in database.
508 //
509 IsFound = TRUE;
510 break;
511 }
512
513 Cert = (EFI_SIGNATURE_DATA *) ((UINT8 *) Cert + CertList->SignatureSize);
514 }
515 if (IsFound) {
516 break;
517 }
518 }
519
1a109376 520 dbsize -= CertList->SignatureListSize;
019b0c5c
MG
521 CertList = (EFI_SIGNATURE_LIST *) ((UINT8 *) CertList + CertList->SignatureListSize);
522 }
523
019b0c5c 524 if (IsFound)
1a109376
MG
525 return DATA_FOUND;
526
527 return DATA_NOT_FOUND;
528}
529
0aee67a8
MG
530/*
531 * Check a hash against an EFI_SIGNATURE_LIST in a UEFI variable
532 */
e0b78774
PJ
533static CHECK_STATUS check_db_hash(CHAR16 *dbname, EFI_GUID guid, UINT8 *data,
534 int SignatureSize, EFI_GUID CertType)
535{
536 EFI_STATUS efi_status;
537 EFI_SIGNATURE_LIST *CertList;
e0b78774 538 UINTN dbsize = 0;
7d602e84 539 UINT8 *db;
e0b78774 540
7d602e84 541 efi_status = get_variable(dbname, &db, &dbsize, guid);
e0b78774
PJ
542
543 if (efi_status != EFI_SUCCESS) {
544 return VAR_NOT_FOUND;
545 }
546
7d602e84 547 CertList = (EFI_SIGNATURE_LIST *)db;
e0b78774
PJ
548
549 CHECK_STATUS rc = check_db_hash_in_ram(CertList, dbsize, data,
550 SignatureSize, CertType);
551 FreePool(db);
552 return rc;
553
554}
555
0aee67a8
MG
556/*
557 * Check whether the binary signature or hash are present in dbx or the
558 * built-in blacklist
559 */
0e054ee1
MG
560static EFI_STATUS check_blacklist (WIN_CERTIFICATE_EFI_PKCS *cert,
561 UINT8 *sha256hash, UINT8 *sha1hash)
1a109376 562{
0848fab9 563 EFI_GUID secure_var = EFI_IMAGE_SECURITY_DATABASE_GUID;
b8d1bc6e 564 EFI_GUID shim_var = SHIM_LOCK_GUID;
23002e8e 565 EFI_SIGNATURE_LIST *dbx = (EFI_SIGNATURE_LIST *)vendor_dbx;
0848fab9 566
23002e8e 567 if (check_db_hash_in_ram(dbx, vendor_dbx_size, sha256hash,
79424b09 568 SHA256_DIGEST_SIZE, EFI_CERT_SHA256_GUID) ==
054dc6d2 569 DATA_FOUND)
6ebf9b87 570 return EFI_SECURITY_VIOLATION;
23002e8e 571 if (check_db_hash_in_ram(dbx, vendor_dbx_size, sha1hash,
79424b09 572 SHA1_DIGEST_SIZE, EFI_CERT_SHA1_GUID) ==
054dc6d2 573 DATA_FOUND)
6ebf9b87 574 return EFI_SECURITY_VIOLATION;
be73f6bd
PJ
575 if (cert && check_db_cert_in_ram(dbx, vendor_dbx_size, cert,
576 sha256hash) == DATA_FOUND)
6ebf9b87 577 return EFI_SECURITY_VIOLATION;
e0b78774 578
0848fab9 579 if (check_db_hash(L"dbx", secure_var, sha256hash, SHA256_DIGEST_SIZE,
79424b09 580 EFI_CERT_SHA256_GUID) == DATA_FOUND)
6ebf9b87 581 return EFI_SECURITY_VIOLATION;
0848fab9 582 if (check_db_hash(L"dbx", secure_var, sha1hash, SHA1_DIGEST_SIZE,
79424b09 583 EFI_CERT_SHA1_GUID) == DATA_FOUND)
6ebf9b87 584 return EFI_SECURITY_VIOLATION;
be73f6bd
PJ
585 if (cert && check_db_cert(L"dbx", secure_var, cert, sha256hash) ==
586 DATA_FOUND)
6ebf9b87 587 return EFI_SECURITY_VIOLATION;
b8d1bc6e
GCPL
588 if (check_db_hash(L"MokListX", shim_var, sha256hash, SHA256_DIGEST_SIZE,
589 EFI_CERT_SHA256_GUID) == DATA_FOUND) {
6ebf9b87 590 return EFI_SECURITY_VIOLATION;
b8d1bc6e
GCPL
591 }
592 if (cert && check_db_cert(L"MokListX", shim_var, cert, sha256hash) ==
593 DATA_FOUND) {
6ebf9b87 594 return EFI_SECURITY_VIOLATION;
b8d1bc6e 595 }
019b0c5c
MG
596
597 return EFI_SUCCESS;
598}
599
39df41ce
PJ
600static void update_verification_method(verification_method_t method)
601{
602 if (verification_method == VERIFIED_BY_NOTHING)
603 verification_method = method;
604}
605
0aee67a8
MG
606/*
607 * Check whether the binary signature or hash are present in db or MokList
608 */
0e054ee1
MG
609static EFI_STATUS check_whitelist (WIN_CERTIFICATE_EFI_PKCS *cert,
610 UINT8 *sha256hash, UINT8 *sha1hash)
85bbd2c4 611{
0848fab9
MG
612 EFI_GUID secure_var = EFI_IMAGE_SECURITY_DATABASE_GUID;
613 EFI_GUID shim_var = SHIM_LOCK_GUID;
614
ef0383d0
JB
615 if (!ignore_db) {
616 if (check_db_hash(L"db", secure_var, sha256hash, SHA256_DIGEST_SIZE,
617 EFI_CERT_SHA256_GUID) == DATA_FOUND) {
618 update_verification_method(VERIFIED_BY_HASH);
619 return EFI_SUCCESS;
620 }
621 if (check_db_hash(L"db", secure_var, sha1hash, SHA1_DIGEST_SIZE,
622 EFI_CERT_SHA1_GUID) == DATA_FOUND) {
623 verification_method = VERIFIED_BY_HASH;
624 update_verification_method(VERIFIED_BY_HASH);
625 return EFI_SUCCESS;
626 }
be73f6bd
PJ
627 if (cert && check_db_cert(L"db", secure_var, cert, sha256hash)
628 == DATA_FOUND) {
ef0383d0
JB
629 verification_method = VERIFIED_BY_CERT;
630 update_verification_method(VERIFIED_BY_CERT);
631 return EFI_SUCCESS;
632 }
39df41ce 633 }
ef0383d0 634
0848fab9 635 if (check_db_hash(L"MokList", shim_var, sha256hash, SHA256_DIGEST_SIZE,
39df41ce
PJ
636 EFI_CERT_SHA256_GUID) == DATA_FOUND) {
637 verification_method = VERIFIED_BY_HASH;
638 update_verification_method(VERIFIED_BY_HASH);
0848fab9 639 return EFI_SUCCESS;
39df41ce 640 }
be73f6bd
PJ
641 if (cert && check_db_cert(L"MokList", shim_var, cert, sha256hash) ==
642 DATA_FOUND) {
39df41ce
PJ
643 verification_method = VERIFIED_BY_CERT;
644 update_verification_method(VERIFIED_BY_CERT);
85bbd2c4 645 return EFI_SUCCESS;
39df41ce 646 }
85bbd2c4 647
39df41ce 648 update_verification_method(VERIFIED_BY_NOTHING);
6ebf9b87 649 return EFI_SECURITY_VIOLATION;
85bbd2c4
MG
650}
651
cc1116ce
MG
652/*
653 * Check whether we're in Secure Boot and user mode
654 */
655
656static BOOLEAN secure_mode (void)
657{
0abed15a 658 static int first = 1;
d95b24bd 659 if (user_insecure_mode)
7127b1ab
MG
660 return FALSE;
661
868b3721 662 if (variable_is_secureboot() != 1) {
0abed15a 663 if (verbose && !in_protocol && first)
dc8fc734 664 console_notify(L"Secure boot not enabled");
0abed15a 665 first = 0;
556c445e
PJ
666 return FALSE;
667 }
cc1116ce 668
eb4cb6a5
PJ
669 /* If we /do/ have "SecureBoot", but /don't/ have "SetupMode",
670 * then the implementation is bad, but we assume that secure boot is
671 * enabled according to the status of "SecureBoot". If we have both
672 * of them, then "SetupMode" may tell us additional data, and we need
673 * to consider it.
674 */
675 if (variable_is_setupmode(0) == 1) {
0abed15a 676 if (verbose && !in_protocol && first)
dc8fc734 677 console_notify(L"Platform is in setup mode");
0abed15a 678 first = 0;
cc1116ce
MG
679 return FALSE;
680 }
681
0abed15a 682 first = 0;
cc1116ce
MG
683 return TRUE;
684}
685
f04d50b7
PJ
686#define check_size_line(data, datasize_in, hashbase, hashsize, l) ({ \
687 if ((unsigned long)hashbase > \
688 (unsigned long)data + datasize_in) { \
03b9f800 689 status = EFI_INVALID_PARAMETER; \
f04d50b7
PJ
690 perror(L"shim.c:%d Invalid hash base 0x%016x\n", l, \
691 hashbase); \
692 goto done; \
693 } \
694 if ((unsigned long)hashbase + hashsize > \
695 (unsigned long)data + datasize_in) { \
03b9f800 696 status = EFI_INVALID_PARAMETER; \
f04d50b7
PJ
697 perror(L"shim.c:%d Invalid hash size 0x%016x\n", l, \
698 hashsize); \
699 goto done; \
700 } \
701})
702#define check_size(d,ds,h,hs) check_size_line(d,ds,h,hs,__LINE__)
703
f898777d 704/*
7f99a97c 705 * Calculate the SHA1 and SHA256 hashes of a binary
f898777d 706 */
7f99a97c 707
750584c2 708static EFI_STATUS generate_hash (char *data, unsigned int datasize_in,
7f99a97c
MG
709 PE_COFF_LOADER_IMAGE_CONTEXT *context,
710 UINT8 *sha256hash, UINT8 *sha1hash)
711
7f055335 712{
0e054ee1 713 unsigned int sha256ctxsize, sha1ctxsize;
5495694c 714 unsigned int size = datasize_in;
0e054ee1 715 void *sha256ctx = NULL, *sha1ctx = NULL;
7f055335
MG
716 char *hashbase;
717 unsigned int hashsize;
7f055335 718 unsigned int SumOfBytesHashed, SumOfSectionBytes;
019b0c5c 719 unsigned int index, pos;
5495694c 720 unsigned int datasize;
7f055335 721 EFI_IMAGE_SECTION_HEADER *Section;
0db1af8a 722 EFI_IMAGE_SECTION_HEADER *SectionHeader = NULL;
7f99a97c 723 EFI_STATUS status = EFI_SUCCESS;
a876037a
PJ
724 EFI_IMAGE_DOS_HEADER *DosHdr = (void *)data;
725 unsigned int PEHdr_offset = 0;
7f055335 726
5495694c 727 if (datasize_in < 0) {
4bfb13d8 728 perror(L"Invalid data size\n");
5495694c
KC
729 return EFI_INVALID_PARAMETER;
730 }
731 size = datasize = (unsigned int)datasize_in;
732
a876037a
PJ
733 if (datasize <= sizeof (*DosHdr) ||
734 DosHdr->e_magic != EFI_IMAGE_DOS_SIGNATURE) {
4bfb13d8 735 perror(L"Invalid signature\n");
a876037a
PJ
736 return EFI_INVALID_PARAMETER;
737 }
738 PEHdr_offset = DosHdr->e_lfanew;
739
740 sha256ctxsize = Sha256GetContextSize();
741 sha256ctx = AllocatePool(sha256ctxsize);
742
743 sha1ctxsize = Sha1GetContextSize();
744 sha1ctx = AllocatePool(sha1ctxsize);
745
0e054ee1 746 if (!sha256ctx || !sha1ctx) {
4bfb13d8 747 perror(L"Unable to allocate memory for hash context\n");
7f055335
MG
748 return EFI_OUT_OF_RESOURCES;
749 }
750
0e054ee1 751 if (!Sha256Init(sha256ctx) || !Sha1Init(sha1ctx)) {
4bfb13d8 752 perror(L"Unable to initialise hash\n");
7f055335
MG
753 status = EFI_OUT_OF_RESOURCES;
754 goto done;
755 }
756
757 /* Hash start to checksum */
7db60bd8 758 hashbase = data;
7f055335
MG
759 hashsize = (char *)&context->PEHdr->Pe32.OptionalHeader.CheckSum -
760 hashbase;
f04d50b7 761 check_size(data, datasize_in, hashbase, hashsize);
7f055335 762
0e054ee1
MG
763 if (!(Sha256Update(sha256ctx, hashbase, hashsize)) ||
764 !(Sha1Update(sha1ctx, hashbase, hashsize))) {
4bfb13d8 765 perror(L"Unable to generate hash\n");
7f055335
MG
766 status = EFI_OUT_OF_RESOURCES;
767 goto done;
768 }
769
770 /* Hash post-checksum to start of certificate table */
771 hashbase = (char *)&context->PEHdr->Pe32.OptionalHeader.CheckSum +
772 sizeof (int);
773 hashsize = (char *)context->SecDir - hashbase;
f04d50b7 774 check_size(data, datasize_in, hashbase, hashsize);
7f055335 775
0e054ee1
MG
776 if (!(Sha256Update(sha256ctx, hashbase, hashsize)) ||
777 !(Sha1Update(sha1ctx, hashbase, hashsize))) {
4bfb13d8 778 perror(L"Unable to generate hash\n");
7f055335
MG
779 status = EFI_OUT_OF_RESOURCES;
780 goto done;
781 }
782
783 /* Hash end of certificate table to end of image header */
750584c2
PJ
784 EFI_IMAGE_DATA_DIRECTORY *dd = context->SecDir + 1;
785 hashbase = (char *)dd;
786 hashsize = context->SizeOfHeaders - (unsigned long)((char *)dd - data);
787 if (hashsize > datasize_in) {
788 perror(L"Data Directory size %d is invalid\n", hashsize);
789 status = EFI_INVALID_PARAMETER;
790 goto done;
791 }
f04d50b7 792 check_size(data, datasize_in, hashbase, hashsize);
0db1af8a 793
0e054ee1
MG
794 if (!(Sha256Update(sha256ctx, hashbase, hashsize)) ||
795 !(Sha1Update(sha1ctx, hashbase, hashsize))) {
4bfb13d8 796 perror(L"Unable to generate hash\n");
7f055335
MG
797 status = EFI_OUT_OF_RESOURCES;
798 goto done;
799 }
800
f898777d 801 /* Sort sections */
750584c2 802 SumOfBytesHashed = context->SizeOfHeaders;
7f055335 803
5495694c 804 /* Validate section locations and sizes */
5103c3b3 805 for (index = 0, SumOfSectionBytes = 0; index < context->PEHdr->Pe32.FileHeader.NumberOfSections; index++) {
5495694c
KC
806 EFI_IMAGE_SECTION_HEADER *SectionPtr;
807
808 /* Validate SectionPtr is within image */
809 SectionPtr = ImageAddress(data, datasize,
a876037a 810 PEHdr_offset +
5495694c
KC
811 sizeof (UINT32) +
812 sizeof (EFI_IMAGE_FILE_HEADER) +
813 context->PEHdr->Pe32.FileHeader.SizeOfOptionalHeader +
814 (index * sizeof(*SectionPtr)));
815 if (!SectionPtr) {
4bfb13d8 816 perror(L"Malformed section %d\n", index);
5495694c
KC
817 status = EFI_INVALID_PARAMETER;
818 goto done;
819 }
820 /* Validate section size is within image. */
821 if (SectionPtr->SizeOfRawData >
822 datasize - SumOfBytesHashed - SumOfSectionBytes) {
4bfb13d8 823 perror(L"Malformed section %d size\n", index);
5495694c
KC
824 status = EFI_INVALID_PARAMETER;
825 goto done;
826 }
827 SumOfSectionBytes += SectionPtr->SizeOfRawData;
7f055335
MG
828 }
829
830 SectionHeader = (EFI_IMAGE_SECTION_HEADER *) AllocateZeroPool (sizeof (EFI_IMAGE_SECTION_HEADER) * context->PEHdr->Pe32.FileHeader.NumberOfSections);
831 if (SectionHeader == NULL) {
4bfb13d8 832 perror(L"Unable to allocate section header\n");
7f055335
MG
833 status = EFI_OUT_OF_RESOURCES;
834 goto done;
835 }
836
5495694c 837 /* Already validated above */
a876037a
PJ
838 Section = ImageAddress(data, datasize,
839 PEHdr_offset +
840 sizeof (UINT32) +
5495694c
KC
841 sizeof (EFI_IMAGE_FILE_HEADER) +
842 context->PEHdr->Pe32.FileHeader.SizeOfOptionalHeader);
843
7f055335
MG
844 /* Sort the section headers */
845 for (index = 0; index < context->PEHdr->Pe32.FileHeader.NumberOfSections; index++) {
846 pos = index;
847 while ((pos > 0) && (Section->PointerToRawData < SectionHeader[pos - 1].PointerToRawData)) {
848 CopyMem (&SectionHeader[pos], &SectionHeader[pos - 1], sizeof (EFI_IMAGE_SECTION_HEADER));
849 pos--;
850 }
851 CopyMem (&SectionHeader[pos], Section, sizeof (EFI_IMAGE_SECTION_HEADER));
852 Section += 1;
853 }
854
855 /* Hash the sections */
856 for (index = 0; index < context->PEHdr->Pe32.FileHeader.NumberOfSections; index++) {
857 Section = &SectionHeader[index];
858 if (Section->SizeOfRawData == 0) {
859 continue;
860 }
56fb385a 861 hashbase = ImageAddress(data, size, Section->PointerToRawData);
7f055335 862
f898777d 863 if (!hashbase) {
4bfb13d8 864 perror(L"Malformed section header\n");
9913079b
MG
865 status = EFI_INVALID_PARAMETER;
866 goto done;
f898777d
MG
867 }
868
5495694c
KC
869 /* Verify hashsize within image. */
870 if (Section->SizeOfRawData >
871 datasize - Section->PointerToRawData) {
4bfb13d8 872 perror(L"Malformed section raw size %d\n", index);
5495694c
KC
873 status = EFI_INVALID_PARAMETER;
874 goto done;
875 }
876 hashsize = (unsigned int) Section->SizeOfRawData;
f04d50b7 877 check_size(data, datasize_in, hashbase, hashsize);
5495694c 878
0e054ee1
MG
879 if (!(Sha256Update(sha256ctx, hashbase, hashsize)) ||
880 !(Sha1Update(sha1ctx, hashbase, hashsize))) {
4bfb13d8 881 perror(L"Unable to generate hash\n");
7f055335
MG
882 status = EFI_OUT_OF_RESOURCES;
883 goto done;
884 }
885 SumOfBytesHashed += Section->SizeOfRawData;
886 }
887
888 /* Hash all remaining data */
5495694c 889 if (datasize > SumOfBytesHashed) {
7db60bd8 890 hashbase = data + SumOfBytesHashed;
750584c2 891 hashsize = datasize - context->SecDir->Size - SumOfBytesHashed;
03b9f800
PJ
892
893 if ((datasize - SumOfBytesHashed < context->SecDir->Size) ||
6dd948b5 894 (SumOfBytesHashed + hashsize != context->SecDir->VirtualAddress)) {
03b9f800
PJ
895 perror(L"Malformed binary after Attribute Certificate Table\n");
896 status = EFI_INVALID_PARAMETER;
897 goto done;
898 }
f04d50b7 899 check_size(data, datasize_in, hashbase, hashsize);
7f055335 900
0e054ee1
MG
901 if (!(Sha256Update(sha256ctx, hashbase, hashsize)) ||
902 !(Sha1Update(sha1ctx, hashbase, hashsize))) {
4bfb13d8 903 perror(L"Unable to generate hash\n");
7f055335
MG
904 status = EFI_OUT_OF_RESOURCES;
905 goto done;
906 }
907 }
908
0e054ee1
MG
909 if (!(Sha256Final(sha256ctx, sha256hash)) ||
910 !(Sha1Final(sha1ctx, sha1hash))) {
4bfb13d8 911 perror(L"Unable to finalise hash\n");
7f055335
MG
912 status = EFI_OUT_OF_RESOURCES;
913 goto done;
914 }
915
7f99a97c
MG
916done:
917 if (SectionHeader)
918 FreePool(SectionHeader);
919 if (sha1ctx)
920 FreePool(sha1ctx);
921 if (sha256ctx)
922 FreePool(sha256ctx);
923
924 return status;
925}
926
0aee67a8
MG
927/*
928 * Ensure that the MOK database hasn't been set or modified from an OS
929 */
0848fab9
MG
930static EFI_STATUS verify_mok (void) {
931 EFI_GUID shim_lock_guid = SHIM_LOCK_GUID;
932 EFI_STATUS status = EFI_SUCCESS;
7d602e84 933 UINT8 *MokListData = NULL;
0848fab9
MG
934 UINTN MokListDataSize = 0;
935 UINT32 attributes;
936
7d602e84
GCPL
937 status = get_variable_attr(L"MokList", &MokListData, &MokListDataSize,
938 shim_lock_guid, &attributes);
0848fab9 939
11495d40 940 if (!EFI_ERROR(status) && attributes & EFI_VARIABLE_RUNTIME_ACCESS) {
4bfb13d8 941 perror(L"MokList is compromised!\nErase all keys in MokList!\n");
0848fab9 942 if (LibDeleteVariable(L"MokList", &shim_lock_guid) != EFI_SUCCESS) {
4bfb13d8 943 perror(L"Failed to erase MokList\n");
6ebf9b87 944 return EFI_SECURITY_VIOLATION;
0848fab9 945 }
0848fab9
MG
946 }
947
804f8f77
GCPL
948 if (MokListData)
949 FreePool(MokListData);
950
0848fab9
MG
951 return EFI_SUCCESS;
952}
953
7f99a97c
MG
954/*
955 * Check that the signature is valid and matches the binary
956 */
957static EFI_STATUS verify_buffer (char *data, int datasize,
0848fab9 958 PE_COFF_LOADER_IMAGE_CONTEXT *context)
7f99a97c 959{
7f99a97c
MG
960 UINT8 sha256hash[SHA256_DIGEST_SIZE];
961 UINT8 sha1hash[SHA1_DIGEST_SIZE];
6ebf9b87 962 EFI_STATUS status = EFI_SECURITY_VIOLATION;
be73f6bd 963 WIN_CERTIFICATE_EFI_PKCS *cert = NULL;
7f99a97c
MG
964 unsigned int size = datasize;
965
be73f6bd 966 if (context->SecDir->Size != 0) {
2de08468
PJ
967 if (context->SecDir->Size >= size) {
968 perror(L"Certificate Database size is too large\n");
969 return EFI_INVALID_PARAMETER;
970 }
971
be73f6bd
PJ
972 cert = ImageAddress (data, size,
973 context->SecDir->VirtualAddress);
bceadba4 974
be73f6bd 975 if (!cert) {
4bfb13d8 976 perror(L"Certificate located outside the image\n");
be73f6bd
PJ
977 return EFI_INVALID_PARAMETER;
978 }
7f99a97c 979
2de08468
PJ
980 if (cert->Hdr.dwLength > context->SecDir->Size) {
981 perror(L"Certificate list size is inconsistent with PE headers");
982 return EFI_INVALID_PARAMETER;
983 }
984
be73f6bd
PJ
985 if (cert->Hdr.wCertificateType !=
986 WIN_CERT_TYPE_PKCS_SIGNED_DATA) {
4bfb13d8 987 perror(L"Unsupported certificate type %x\n",
be73f6bd
PJ
988 cert->Hdr.wCertificateType);
989 return EFI_UNSUPPORTED;
990 }
7f99a97c
MG
991 }
992
993 status = generate_hash(data, datasize, context, sha256hash, sha1hash);
7f99a97c
MG
994 if (status != EFI_SUCCESS)
995 return status;
996
0aee67a8
MG
997 /*
998 * Check that the MOK database hasn't been modified
999 */
11495d40
AB
1000 status = verify_mok();
1001 if (status != EFI_SUCCESS)
1002 return status;
0848fab9 1003
0aee67a8
MG
1004 /*
1005 * Ensure that the binary isn't blacklisted
1006 */
0e054ee1 1007 status = check_blacklist(cert, sha256hash, sha1hash);
019b0c5c 1008 if (status != EFI_SUCCESS) {
4bfb13d8 1009 perror(L"Binary is blacklisted\n");
7f99a97c 1010 return status;
019b0c5c
MG
1011 }
1012
0aee67a8
MG
1013 /*
1014 * Check whether the binary is whitelisted in any of the firmware
1015 * databases
1016 */
0848fab9 1017 status = check_whitelist(cert, sha256hash, sha1hash);
880f9de4 1018 if (status == EFI_SUCCESS)
0848fab9 1019 return status;
85bbd2c4 1020
be73f6bd
PJ
1021 if (cert) {
1022 /*
1023 * Check against the shim build key
1024 */
db43ba5a
GCPL
1025 if (sizeof(shim_cert) &&
1026 AuthenticodeVerify(cert->CertData,
d241bbbd 1027 cert->Hdr.dwLength - sizeof(cert->Hdr),
6d50f87a
MG
1028 shim_cert, sizeof(shim_cert), sha256hash,
1029 SHA256_DIGEST_SIZE)) {
be73f6bd
PJ
1030 status = EFI_SUCCESS;
1031 return status;
1032 }
6d50f87a 1033
be73f6bd
PJ
1034 /*
1035 * And finally, check against shim's built-in key
1036 */
b8e27b3c
PJ
1037 if (vendor_cert_size &&
1038 AuthenticodeVerify(cert->CertData,
1039 cert->Hdr.dwLength - sizeof(cert->Hdr),
1040 vendor_cert, vendor_cert_size,
1041 sha256hash, SHA256_DIGEST_SIZE)) {
be73f6bd
PJ
1042 status = EFI_SUCCESS;
1043 return status;
1044 }
28c58133
GCPL
1045 }
1046
6ebf9b87 1047 status = EFI_SECURITY_VIOLATION;
f898777d
MG
1048 return status;
1049}
b2fe1780 1050
f898777d
MG
1051/*
1052 * Read the binary header and grab appropriate information from it
1053 */
3682a895 1054static EFI_STATUS read_header(void *data, unsigned int datasize,
f898777d
MG
1055 PE_COFF_LOADER_IMAGE_CONTEXT *context)
1056{
7db60bd8
MG
1057 EFI_IMAGE_DOS_HEADER *DosHdr = data;
1058 EFI_IMAGE_OPTIONAL_HEADER_UNION *PEHdr = data;
8e9d3af7 1059 unsigned long HeaderWithoutDataDir, SectionHeaderOffset, OptHeaderSize;
467878f3 1060 unsigned long FileAlignment = 0;
b2fe1780 1061
750584c2 1062 if (datasize < sizeof (PEHdr->Pe32)) {
4bfb13d8 1063 perror(L"Invalid image\n");
9913079b
MG
1064 return EFI_UNSUPPORTED;
1065 }
1066
f898777d 1067 if (DosHdr->e_magic == EFI_IMAGE_DOS_SIGNATURE)
7db60bd8 1068 PEHdr = (EFI_IMAGE_OPTIONAL_HEADER_UNION *)((char *)data + DosHdr->e_lfanew);
750584c2
PJ
1069
1070 if (!image_is_loadable(PEHdr)) {
1071 perror(L"Platform does not support this image\n");
1072 return EFI_UNSUPPORTED;
1073 }
1074
1075 if (image_is_64_bit(PEHdr)) {
1076 context->NumberOfRvaAndSizes = PEHdr->Pe32Plus.OptionalHeader.NumberOfRvaAndSizes;
1077 context->SizeOfHeaders = PEHdr->Pe32Plus.OptionalHeader.SizeOfHeaders;
1078 context->ImageSize = PEHdr->Pe32Plus.OptionalHeader.SizeOfImage;
d01421eb 1079 context->SectionAlignment = PEHdr->Pe32Plus.OptionalHeader.SectionAlignment;
467878f3 1080 FileAlignment = PEHdr->Pe32Plus.OptionalHeader.FileAlignment;
750584c2
PJ
1081 OptHeaderSize = sizeof(EFI_IMAGE_OPTIONAL_HEADER64);
1082 } else {
1083 context->NumberOfRvaAndSizes = PEHdr->Pe32.OptionalHeader.NumberOfRvaAndSizes;
1084 context->SizeOfHeaders = PEHdr->Pe32.OptionalHeader.SizeOfHeaders;
1085 context->ImageSize = (UINT64)PEHdr->Pe32.OptionalHeader.SizeOfImage;
d01421eb 1086 context->SectionAlignment = PEHdr->Pe32.OptionalHeader.SectionAlignment;
467878f3 1087 FileAlignment = PEHdr->Pe32.OptionalHeader.FileAlignment;
750584c2
PJ
1088 OptHeaderSize = sizeof(EFI_IMAGE_OPTIONAL_HEADER32);
1089 }
1090
467878f3
PJ
1091 if (FileAlignment % 2 != 0) {
1092 perror(L"File Alignment is invalid (%d)\n", FileAlignment);
1093 return EFI_UNSUPPORTED;
1094 }
1095 if (FileAlignment == 0)
1096 FileAlignment = 0x200;
1097 if (context->SectionAlignment == 0)
1098 context->SectionAlignment = PAGE_SIZE;
1099 if (context->SectionAlignment < FileAlignment)
1100 context->SectionAlignment = FileAlignment;
1101
8e9d3af7 1102 context->NumberOfSections = PEHdr->Pe32.FileHeader.NumberOfSections;
b2fe1780 1103
8e9d3af7 1104 if (EFI_IMAGE_NUMBER_OF_DIRECTORY_ENTRIES < context->NumberOfRvaAndSizes) {
4bfb13d8 1105 perror(L"Image header too small\n");
53a318f5
PJ
1106 return EFI_UNSUPPORTED;
1107 }
1108
8e9d3af7 1109 HeaderWithoutDataDir = OptHeaderSize
53a318f5 1110 - sizeof (EFI_IMAGE_DATA_DIRECTORY) * EFI_IMAGE_NUMBER_OF_DIRECTORY_ENTRIES;
8e9d3af7
M
1111 if (((UINT32)PEHdr->Pe32.FileHeader.SizeOfOptionalHeader - HeaderWithoutDataDir) !=
1112 context->NumberOfRvaAndSizes * sizeof (EFI_IMAGE_DATA_DIRECTORY)) {
4bfb13d8 1113 perror(L"Image header overflows data directory\n");
53a318f5
PJ
1114 return EFI_UNSUPPORTED;
1115 }
1116
1117 SectionHeaderOffset = DosHdr->e_lfanew
1118 + sizeof (UINT32)
1119 + sizeof (EFI_IMAGE_FILE_HEADER)
8e9d3af7
M
1120 + PEHdr->Pe32.FileHeader.SizeOfOptionalHeader;
1121 if (((UINT32)context->ImageSize - SectionHeaderOffset) / EFI_IMAGE_SIZEOF_SECTION_HEADER
1122 <= context->NumberOfSections) {
4bfb13d8 1123 perror(L"Image sections overflow image size\n");
53a318f5
PJ
1124 return EFI_UNSUPPORTED;
1125 }
1126
8e9d3af7
M
1127 if ((context->SizeOfHeaders - SectionHeaderOffset) / EFI_IMAGE_SIZEOF_SECTION_HEADER
1128 < (UINT32)context->NumberOfSections) {
4bfb13d8 1129 perror(L"Image sections overflow section headers\n");
53a318f5
PJ
1130 return EFI_UNSUPPORTED;
1131 }
1132
9913079b 1133 if ((((UINT8 *)PEHdr - (UINT8 *)data) + sizeof(EFI_IMAGE_OPTIONAL_HEADER_UNION)) > datasize) {
4bfb13d8 1134 perror(L"Invalid image\n");
9913079b
MG
1135 return EFI_UNSUPPORTED;
1136 }
1137
f898777d 1138 if (PEHdr->Te.Signature != EFI_IMAGE_NT_SIGNATURE) {
4bfb13d8 1139 perror(L"Unsupported image type\n");
f898777d
MG
1140 return EFI_UNSUPPORTED;
1141 }
b2fe1780 1142
f898777d 1143 if (PEHdr->Pe32.FileHeader.Characteristics & EFI_IMAGE_FILE_RELOCS_STRIPPED) {
4bfb13d8 1144 perror(L"Unsupported image - Relocations have been stripped\n");
f898777d
MG
1145 return EFI_UNSUPPORTED;
1146 }
b2fe1780 1147
f898777d 1148 context->PEHdr = PEHdr;
750584c2
PJ
1149
1150 if (image_is_64_bit(PEHdr)) {
1151 context->ImageAddress = PEHdr->Pe32Plus.OptionalHeader.ImageBase;
1152 context->EntryPoint = PEHdr->Pe32Plus.OptionalHeader.AddressOfEntryPoint;
1153 context->RelocDir = &PEHdr->Pe32Plus.OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC];
1154 context->SecDir = &PEHdr->Pe32Plus.OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY];
1155 } else {
1156 context->ImageAddress = PEHdr->Pe32.OptionalHeader.ImageBase;
1157 context->EntryPoint = PEHdr->Pe32.OptionalHeader.AddressOfEntryPoint;
1158 context->RelocDir = &PEHdr->Pe32.OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC];
1159 context->SecDir = &PEHdr->Pe32.OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY];
1160 }
1161
8e9d3af7 1162 context->FirstSection = (EFI_IMAGE_SECTION_HEADER *)((char *)PEHdr + PEHdr->Pe32.FileHeader.SizeOfOptionalHeader + sizeof(UINT32) + sizeof(EFI_IMAGE_FILE_HEADER));
b2fe1780 1163
9913079b 1164 if (context->ImageSize < context->SizeOfHeaders) {
4bfb13d8 1165 perror(L"Invalid image\n");
9913079b 1166 return EFI_UNSUPPORTED;
b2fe1780
MG
1167 }
1168
5495694c
KC
1169 if ((unsigned long)((UINT8 *)context->SecDir - (UINT8 *)data) >
1170 (datasize - sizeof(EFI_IMAGE_DATA_DIRECTORY))) {
4bfb13d8 1171 perror(L"Invalid image\n");
9913079b
MG
1172 return EFI_UNSUPPORTED;
1173 }
1174
3682a895 1175 if (context->SecDir->VirtualAddress >= datasize) {
4bfb13d8 1176 perror(L"Malformed security header\n");
f898777d
MG
1177 return EFI_INVALID_PARAMETER;
1178 }
f898777d 1179 return EFI_SUCCESS;
b2fe1780
MG
1180}
1181
f898777d
MG
1182/*
1183 * Once the image has been loaded it needs to be validated and relocated
1184 */
1fe0d49c
GCPL
1185static EFI_STATUS handle_image (void *data, unsigned int datasize,
1186 EFI_LOADED_IMAGE *li)
b2fe1780
MG
1187{
1188 EFI_STATUS efi_status;
1189 char *buffer;
5495694c 1190 int i;
b2fe1780 1191 EFI_IMAGE_SECTION_HEADER *Section;
0e6b0195 1192 char *base, *end;
b2fe1780 1193 PE_COFF_LOADER_IMAGE_CONTEXT context;
97022acd
AB
1194 unsigned int alignment, alloc_size;
1195 EFI_PHYSICAL_ADDRESS alloc_address;
14a59055 1196 int found_entry_point = 0;
7f055335 1197
0aee67a8
MG
1198 /*
1199 * The binary header contains relevant context and section pointers
1200 */
3682a895 1201 efi_status = read_header(data, datasize, &context);
b2fe1780 1202 if (efi_status != EFI_SUCCESS) {
4bfb13d8 1203 perror(L"Failed to read header: %r\n", efi_status);
b2fe1780
MG
1204 return efi_status;
1205 }
1206
0aee67a8
MG
1207 /*
1208 * We only need to verify the binary if we're in secure mode
1209 */
cc1116ce 1210 if (secure_mode ()) {
0848fab9 1211 efi_status = verify_buffer(data, datasize, &context);
7f055335 1212
880f9de4
PJ
1213 if (EFI_ERROR(efi_status)) {
1214 console_error(L"Verification failed", efi_status);
cc1116ce 1215 return efi_status;
880f9de4
PJ
1216 } else {
1217 if (verbose)
1218 console_notify(L"Verification succeeded");
cc1116ce 1219 }
7f055335
MG
1220 }
1221
14a59055
PJ
1222 /* The spec says, uselessly, of SectionAlignment:
1223 * =====
1224 * The alignment (in bytes) of sections when they are loaded into
1225 * memory. It must be greater than or equal to FileAlignment. The
1226 * default is the page size for the architecture.
1227 * =====
1228 * Which doesn't tell you whose responsibility it is to enforce the
1229 * "default", or when. It implies that the value in the field must
1230 * be > FileAlignment (also poorly defined), but it appears visual
1231 * studio will happily write 512 for FileAlignment (its default) and
1232 * 0 for SectionAlignment, intending to imply PAGE_SIZE.
1233 *
1234 * We only support one page size, so if it's zero, nerf it to 4096.
1235 */
1236 alignment = context.SectionAlignment;
1237 if (!alignment)
1238 alignment = 4096;
1239
97022acd
AB
1240 alloc_size = ALIGN_VALUE(context.ImageSize + context.SectionAlignment,
1241 PAGE_SIZE);
b2fe1780 1242
97022acd
AB
1243 efi_status = uefi_call_wrapper (BS->AllocatePages, 4,
1244 AllocateAnyPages,
1245 EfiLoaderCode,
1246 alloc_size / PAGE_SIZE,
1247 &alloc_address);
1248
1249 if (efi_status != EFI_SUCCESS) {
4bfb13d8 1250 perror(L"Failed to allocate image buffer\n");
0e6b0195
MG
1251 return EFI_OUT_OF_RESOURCES;
1252 }
1253
97022acd
AB
1254 buffer = (void *)ALIGN_VALUE((unsigned long)alloc_address, alignment);
1255
7db60bd8 1256 CopyMem(buffer, data, context.SizeOfHeaders);
b2fe1780 1257
14a59055
PJ
1258 entry_point = ImageAddress(buffer, context.ImageSize, context.EntryPoint);
1259 if (!entry_point) {
1260 perror(L"Entry point is invalid\n");
97022acd
AB
1261 uefi_call_wrapper(BS->FreePages, 2, alloc_address,
1262 alloc_size / PAGE_SIZE);
14a59055
PJ
1263 return EFI_UNSUPPORTED;
1264 }
1265
1266
a846aedd 1267 char *RelocBase, *RelocBaseEnd;
14a59055
PJ
1268 /*
1269 * These are relative virtual addresses, so we have to check them
1270 * against the image size, not the data size.
1271 */
1272 RelocBase = ImageAddress(buffer, context.ImageSize,
a846aedd 1273 context.RelocDir->VirtualAddress);
14a59055
PJ
1274 /*
1275 * RelocBaseEnd here is the address of the last byte of the table
1276 */
1277 RelocBaseEnd = ImageAddress(buffer, context.ImageSize,
a846aedd
PJ
1278 context.RelocDir->VirtualAddress +
1279 context.RelocDir->Size - 1);
1280
1281 EFI_IMAGE_SECTION_HEADER *RelocSection = NULL;
1282
0aee67a8
MG
1283 /*
1284 * Copy the executable's sections to their desired offsets
1285 */
b2fe1780 1286 Section = context.FirstSection;
94c9a77f 1287 for (i = 0; i < context.NumberOfSections; i++, Section++) {
14a59055
PJ
1288 base = ImageAddress (buffer, context.ImageSize,
1289 Section->VirtualAddress);
1290 end = ImageAddress (buffer, context.ImageSize,
1291 Section->VirtualAddress
1292 + Section->Misc.VirtualSize - 1);
1293
1294 if (end < base) {
1295 perror(L"Section %d has negative size\n", i);
97022acd
AB
1296 uefi_call_wrapper(BS->FreePages, 2, alloc_address,
1297 alloc_size / PAGE_SIZE);
14a59055
PJ
1298 return EFI_UNSUPPORTED;
1299 }
b2fe1780 1300
14a59055
PJ
1301 if (Section->VirtualAddress <= context.EntryPoint &&
1302 (Section->VirtualAddress + Section->SizeOfRawData - 1)
1303 > context.EntryPoint)
1304 found_entry_point++;
b2fe1780 1305
a846aedd
PJ
1306 /* We do want to process .reloc, but it's often marked
1307 * discardable, so we don't want to memcpy it. */
1308 if (CompareMem(Section->Name, ".reloc\0\0", 8) == 0) {
1309 if (RelocSection) {
1310 perror(L"Image has multiple relocation sections\n");
1311 return EFI_UNSUPPORTED;
1312 }
1313 /* If it has nonzero sizes, and our bounds check
1314 * made sense, and the VA and size match RelocDir's
1315 * versions, then we believe in this section table. */
1316 if (Section->SizeOfRawData &&
1317 Section->Misc.VirtualSize &&
1318 base && end &&
1319 RelocBase == base &&
1320 RelocBaseEnd == end) {
1321 RelocSection = Section;
1322 }
1323 }
1324
14a59055 1325 if (Section->Characteristics & EFI_IMAGE_SCN_MEM_DISCARDABLE) {
a846aedd
PJ
1326 continue;
1327 }
1328
14a59055
PJ
1329 if (!base) {
1330 perror(L"Section %d has invalid base address\n", i);
1331 return EFI_UNSUPPORTED;
1332 }
1333 if (!end) {
1334 perror(L"Section %d has zero size\n", i);
d01421eb
PJ
1335 return EFI_UNSUPPORTED;
1336 }
1337
14a59055
PJ
1338 if (!(Section->Characteristics & EFI_IMAGE_SCN_CNT_UNINITIALIZED_DATA) &&
1339 (Section->VirtualAddress < context.SizeOfHeaders ||
1340 Section->PointerToRawData < context.SizeOfHeaders)) {
d01421eb
PJ
1341 perror(L"Section %d is inside image headers\n", i);
1342 return EFI_UNSUPPORTED;
1343 }
1344
467878f3
PJ
1345 if (Section->Characteristics & EFI_IMAGE_SCN_CNT_UNINITIALIZED_DATA) {
1346 ZeroMem(base, Section->Misc.VirtualSize);
1347 } else {
1348 if (Section->PointerToRawData < context.SizeOfHeaders) {
1349 perror(L"Section %d is inside image headers\n", i);
1350 return EFI_UNSUPPORTED;
1351 }
1352
1353 if (Section->SizeOfRawData > 0)
af13b3ef
PJ
1354 CopyMem(base, data + Section->PointerToRawData,
1355 Section->SizeOfRawData);
b2fe1780 1356
af13b3ef
PJ
1357 if (Section->SizeOfRawData < Section->Misc.VirtualSize)
1358 ZeroMem(base + Section->SizeOfRawData,
1359 Section->Misc.VirtualSize - Section->SizeOfRawData);
467878f3 1360 }
b2fe1780
MG
1361 }
1362
a7249a65
PJ
1363 if (context.NumberOfRvaAndSizes <= EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC) {
1364 perror(L"Image has no relocation entry\n");
0db1af8a 1365 FreePool(buffer);
a7249a65
PJ
1366 return EFI_UNSUPPORTED;
1367 }
1368
a846aedd 1369 if (context.RelocDir->Size && RelocSection) {
a7249a65
PJ
1370 /*
1371 * Run the relocation fixups
1372 */
a846aedd
PJ
1373 efi_status = relocate_coff(&context, RelocSection, data,
1374 buffer);
a7249a65
PJ
1375
1376 if (efi_status != EFI_SUCCESS) {
1377 perror(L"Relocation failed: %r\n", efi_status);
1378 FreePool(buffer);
1379 return efi_status;
1380 }
b2fe1780
MG
1381 }
1382
0aee67a8
MG
1383 /*
1384 * grub needs to know its location and size in memory, so fix up
1385 * the loaded image protocol values
1386 */
8c173876
MG
1387 li->ImageBase = buffer;
1388 li->ImageSize = context.ImageSize;
1389
14d4b8e5
GCPL
1390 /* Pass the load options to the second stage loader */
1391 li->LoadOptions = load_options;
1392 li->LoadOptionsSize = load_options_size;
1393
14a59055
PJ
1394 if (!found_entry_point) {
1395 perror(L"Entry point is not within sections\n");
1396 return EFI_UNSUPPORTED;
1397 }
1398 if (found_entry_point > 1) {
1399 perror(L"%d sections contain entry point\n");
0e6b0195
MG
1400 return EFI_UNSUPPORTED;
1401 }
b2fe1780
MG
1402
1403 return EFI_SUCCESS;
1404}
1405
a24d3ba3
PJ
1406static int
1407should_use_fallback(EFI_HANDLE image_handle)
1408{
1409 EFI_GUID loaded_image_protocol = LOADED_IMAGE_PROTOCOL;
1410 EFI_LOADED_IMAGE *li;
a24d3ba3 1411 unsigned int pathlen = 0;
c36d88cb 1412 CHAR16 *bootpath = NULL;
a24d3ba3 1413 EFI_FILE_IO_INTERFACE *fio = NULL;
47948224
PJ
1414 EFI_FILE *vh = NULL;
1415 EFI_FILE *fh = NULL;
a24d3ba3 1416 EFI_STATUS rc;
c36d88cb 1417 int ret = 0;
a24d3ba3
PJ
1418
1419 rc = uefi_call_wrapper(BS->HandleProtocol, 3, image_handle,
1420 &loaded_image_protocol, (void **)&li);
b0712c5f 1421 if (EFI_ERROR(rc)) {
4bfb13d8 1422 perror(L"Could not get image for bootx64.efi: %r\n", rc);
a24d3ba3 1423 return 0;
b0712c5f 1424 }
a24d3ba3 1425
df87084f 1426 bootpath = DevicePathToStr(li->FilePath);
a24d3ba3
PJ
1427
1428 /* Check the beginning of the string and the end, to avoid
1429 * caring about which arch this is. */
1430 /* I really don't know why, but sometimes bootpath gives us
1431 * L"\\EFI\\BOOT\\/BOOTX64.EFI". So just handle that here...
1432 */
1433 if (StrnCaseCmp(bootpath, L"\\EFI\\BOOT\\BOOT", 14) &&
edeb313e
PJ
1434 StrnCaseCmp(bootpath, L"\\EFI\\BOOT\\/BOOT", 15) &&
1435 StrnCaseCmp(bootpath, L"EFI\\BOOT\\BOOT", 13) &&
1436 StrnCaseCmp(bootpath, L"EFI\\BOOT\\/BOOT", 14))
c36d88cb 1437 goto error;
df87084f 1438
a24d3ba3
PJ
1439 pathlen = StrLen(bootpath);
1440 if (pathlen < 5 || StrCaseCmp(bootpath + pathlen - 4, L".EFI"))
c36d88cb 1441 goto error;
a24d3ba3 1442
a24d3ba3 1443 rc = uefi_call_wrapper(BS->HandleProtocol, 3, li->DeviceHandle,
073f3b3c 1444 &FileSystemProtocol, (void **)&fio);
b0712c5f 1445 if (EFI_ERROR(rc)) {
4bfb13d8 1446 perror(L"Could not get fio for li->DeviceHandle: %r\n", rc);
c36d88cb 1447 goto error;
b0712c5f 1448 }
4bfb13d8 1449
a24d3ba3 1450 rc = uefi_call_wrapper(fio->OpenVolume, 2, fio, &vh);
b0712c5f 1451 if (EFI_ERROR(rc)) {
4bfb13d8 1452 perror(L"Could not open fio volume: %r\n", rc);
c36d88cb 1453 goto error;
b0712c5f 1454 }
a24d3ba3
PJ
1455
1456 rc = uefi_call_wrapper(vh->Open, 5, vh, &fh, L"\\EFI\\BOOT" FALLBACK,
1da87c00 1457 EFI_FILE_MODE_READ, 0);
a24d3ba3 1458 if (EFI_ERROR(rc)) {
41e18d43
PJ
1459 /* Do not print the error here - this is an acceptable case
1460 * for removable media, where we genuinely don't want
1461 * fallback.efi to exist.
1462 * Print(L"Could not open \"\\EFI\\BOOT%s\": %d\n", FALLBACK,
1463 * rc);
1464 */
c36d88cb 1465 goto error;
a24d3ba3 1466 }
a24d3ba3 1467
c36d88cb
GCPL
1468 ret = 1;
1469error:
47948224
PJ
1470 if (fh)
1471 uefi_call_wrapper(fh->Close, 1, fh);
1472 if (vh)
1473 uefi_call_wrapper(vh->Close, 1, vh);
c36d88cb
GCPL
1474 if (bootpath)
1475 FreePool(bootpath);
1476
1477 return ret;
a24d3ba3
PJ
1478}
1479
0aee67a8
MG
1480/*
1481 * Generate the path of an executable given shim's path and the name
1482 * of the executable
1483 */
e235c85a 1484static EFI_STATUS generate_path(EFI_LOADED_IMAGE *li, CHAR16 *ImagePath,
78aaad30 1485 CHAR16 **PathName)
f898777d 1486{
0db1af8a 1487 EFI_DEVICE_PATH *devpath;
5495694c
KC
1488 unsigned int i;
1489 int j, last = -1;
03685963
MG
1490 unsigned int pathlen = 0;
1491 EFI_STATUS efi_status = EFI_SUCCESS;
d3ee0bed 1492 CHAR16 *bootpath;
f898777d 1493
2e655619
PJ
1494 /*
1495 * Suuuuper lazy technique here, but check and see if this is a full
1496 * path to something on the ESP. Backwards compatibility demands
1497 * that we don't just use \\, becuase we (not particularly brightly)
1498 * used to require that the relative file path started with that.
1499 *
1500 * If it is a full path, don't try to merge it with the directory
1501 * from our Loaded Image handle.
1502 */
1503 if (StrSize(ImagePath) > 5 && StrnCmp(ImagePath, L"\\EFI\\", 5) == 0) {
1504 *PathName = StrDuplicate(ImagePath);
1505 if (!*PathName) {
1506 perror(L"Failed to allocate path buffer\n");
1507 return EFI_OUT_OF_RESOURCES;
1508 }
1509 return EFI_SUCCESS;
1510 }
1511
0db1af8a 1512 devpath = li->FilePath;
f898777d 1513
d3ee0bed 1514 bootpath = DevicePathToStr(devpath);
f898777d 1515
d3ee0bed 1516 pathlen = StrLen(bootpath);
f898777d 1517
ca22da9d
GCPL
1518 /*
1519 * DevicePathToStr() concatenates two nodes with '/'.
1520 * Convert '/' to '\\'.
1521 */
1522 for (i = 0; i < pathlen; i++) {
1523 if (bootpath[i] == '/')
1524 bootpath[i] = '\\';
1525 }
aa3dca0b 1526
d3ee0bed 1527 for (i=pathlen; i>0; i--) {
aa3dca0b
GCPL
1528 if (bootpath[i] == '\\' && bootpath[i-1] == '\\')
1529 bootpath[i] = '/';
1530 else if (last == -1 && bootpath[i] == '\\')
1531 last = i;
1532 }
1533
1534 if (last == -1 && bootpath[0] == '\\')
1535 last = 0;
1536 bootpath[last+1] = '\0';
1537
1538 if (last > 0) {
1539 for (i = 0, j = 0; bootpath[i] != '\0'; i++) {
1540 if (bootpath[i] != '/') {
1541 bootpath[j] = bootpath[i];
1542 j++;
1543 }
1544 }
1545 bootpath[j] = '\0';
f898777d
MG
1546 }
1547
ca22da9d
GCPL
1548 while (*ImagePath == '\\')
1549 ImagePath++;
590b3449 1550
e235c85a 1551 *PathName = AllocatePool(StrSize(bootpath) + StrSize(ImagePath));
f898777d 1552
03685963 1553 if (!*PathName) {
4bfb13d8 1554 perror(L"Failed to allocate path buffer\n");
0db1af8a
MG
1555 efi_status = EFI_OUT_OF_RESOURCES;
1556 goto error;
f898777d
MG
1557 }
1558
d3ee0bed 1559 *PathName[0] = '\0';
4df3d7c3
PJ
1560 if (StrnCaseCmp(bootpath, ImagePath, StrLen(bootpath)))
1561 StrCat(*PathName, bootpath);
e235c85a 1562 StrCat(*PathName, ImagePath);
03685963 1563
03685963 1564error:
ca22da9d
GCPL
1565 FreePool(bootpath);
1566
03685963
MG
1567 return efi_status;
1568}
1569
1570/*
0aee67a8 1571 * Open the second stage bootloader and read it into a buffer
03685963 1572 */
e235c85a
GCPL
1573static EFI_STATUS load_image (EFI_LOADED_IMAGE *li, void **data,
1574 int *datasize, CHAR16 *PathName)
03685963
MG
1575{
1576 EFI_GUID simple_file_system_protocol = SIMPLE_FILE_SYSTEM_PROTOCOL;
1577 EFI_GUID file_info_id = EFI_FILE_INFO_ID;
1578 EFI_STATUS efi_status;
1579 EFI_HANDLE device;
1580 EFI_FILE_INFO *fileinfo = NULL;
1581 EFI_FILE_IO_INTERFACE *drive;
1582 EFI_FILE *root, *grub;
6d3e62ef 1583 UINTN buffersize = sizeof(EFI_FILE_INFO);
03685963
MG
1584
1585 device = li->DeviceHandle;
f898777d 1586
0aee67a8
MG
1587 /*
1588 * Open the device
1589 */
0db1af8a 1590 efi_status = uefi_call_wrapper(BS->HandleProtocol, 3, device,
24a602b6
MG
1591 &simple_file_system_protocol,
1592 (void **)&drive);
f898777d 1593
0db1af8a 1594 if (efi_status != EFI_SUCCESS) {
4bfb13d8 1595 perror(L"Failed to find fs: %r\n", efi_status);
0db1af8a
MG
1596 goto error;
1597 }
f898777d 1598
0db1af8a
MG
1599 efi_status = uefi_call_wrapper(drive->OpenVolume, 2, drive, &root);
1600
1601 if (efi_status != EFI_SUCCESS) {
4bfb13d8 1602 perror(L"Failed to open fs: %r\n", efi_status);
0db1af8a
MG
1603 goto error;
1604 }
f898777d 1605
0aee67a8
MG
1606 /*
1607 * And then open the file
1608 */
f898777d
MG
1609 efi_status = uefi_call_wrapper(root->Open, 5, root, &grub, PathName,
1610 EFI_FILE_MODE_READ, 0);
1611
1612 if (efi_status != EFI_SUCCESS) {
4bfb13d8 1613 perror(L"Failed to open %s - %r\n", PathName, efi_status);
0db1af8a
MG
1614 goto error;
1615 }
1616
1617 fileinfo = AllocatePool(buffersize);
1618
1619 if (!fileinfo) {
4bfb13d8 1620 perror(L"Unable to allocate file info buffer\n");
0db1af8a
MG
1621 efi_status = EFI_OUT_OF_RESOURCES;
1622 goto error;
f898777d
MG
1623 }
1624
0aee67a8
MG
1625 /*
1626 * Find out how big the file is in order to allocate the storage
1627 * buffer
1628 */
f898777d
MG
1629 efi_status = uefi_call_wrapper(grub->GetInfo, 4, grub, &file_info_id,
1630 &buffersize, fileinfo);
1631
1632 if (efi_status == EFI_BUFFER_TOO_SMALL) {
9913079b 1633 FreePool(fileinfo);
f898777d
MG
1634 fileinfo = AllocatePool(buffersize);
1635 if (!fileinfo) {
4bfb13d8 1636 perror(L"Unable to allocate file info buffer\n");
0db1af8a
MG
1637 efi_status = EFI_OUT_OF_RESOURCES;
1638 goto error;
f898777d
MG
1639 }
1640 efi_status = uefi_call_wrapper(grub->GetInfo, 4, grub,
1641 &file_info_id, &buffersize,
1642 fileinfo);
1643 }
1644
1645 if (efi_status != EFI_SUCCESS) {
4bfb13d8 1646 perror(L"Unable to get file info: %r\n", efi_status);
0db1af8a 1647 goto error;
f898777d
MG
1648 }
1649
1650 buffersize = fileinfo->FileSize;
0db1af8a 1651
7db60bd8 1652 *data = AllocatePool(buffersize);
f898777d 1653
7db60bd8 1654 if (!*data) {
4bfb13d8 1655 perror(L"Unable to allocate file buffer\n");
0db1af8a
MG
1656 efi_status = EFI_OUT_OF_RESOURCES;
1657 goto error;
f898777d 1658 }
0aee67a8
MG
1659
1660 /*
1661 * Perform the actual read
1662 */
f898777d 1663 efi_status = uefi_call_wrapper(grub->Read, 3, grub, &buffersize,
7db60bd8 1664 *data);
f898777d 1665
0db1af8a
MG
1666 if (efi_status == EFI_BUFFER_TOO_SMALL) {
1667 FreePool(*data);
1668 *data = AllocatePool(buffersize);
1669 efi_status = uefi_call_wrapper(grub->Read, 3, grub,
1670 &buffersize, *data);
f898777d
MG
1671 }
1672
1673 if (efi_status != EFI_SUCCESS) {
4bfb13d8 1674 perror(L"Unexpected return from initial read: %r, buffersize %x\n", efi_status, buffersize);
0db1af8a 1675 goto error;
f898777d
MG
1676 }
1677
7db60bd8 1678 *datasize = buffersize;
f898777d 1679
9913079b
MG
1680 FreePool(fileinfo);
1681
f898777d 1682 return EFI_SUCCESS;
0db1af8a
MG
1683error:
1684 if (*data) {
1685 FreePool(*data);
1686 *data = NULL;
1687 }
53feaa01 1688
0db1af8a
MG
1689 if (fileinfo)
1690 FreePool(fileinfo);
1691 return efi_status;
f898777d
MG
1692}
1693
0aee67a8
MG
1694/*
1695 * Protocol entry point. If secure boot is enabled, verify that the provided
1696 * buffer is signed with a trusted key.
1697 */
03685963 1698EFI_STATUS shim_verify (void *buffer, UINT32 size)
f4b24734 1699{
a0e83076 1700 EFI_STATUS status = EFI_SUCCESS;
f4b24734
MG
1701 PE_COFF_LOADER_IMAGE_CONTEXT context;
1702
39df41ce 1703 loader_is_participating = 1;
4bfb13d8 1704 in_protocol = 1;
39df41ce 1705
cc1116ce 1706 if (!secure_mode())
a0e83076 1707 goto done;
cc1116ce 1708
3682a895 1709 status = read_header(buffer, size, &context);
f4b24734 1710 if (status != EFI_SUCCESS)
4bfb13d8 1711 goto done;
f4b24734 1712
0848fab9 1713 status = verify_buffer(buffer, size, &context);
4bfb13d8
GCPL
1714done:
1715 in_protocol = 0;
1716 return status;
1717}
1718
1719static EFI_STATUS shim_hash (char *data, int datasize,
1720 PE_COFF_LOADER_IMAGE_CONTEXT *context,
1721 UINT8 *sha256hash, UINT8 *sha1hash)
1722{
1723 EFI_STATUS status;
1724
1725 in_protocol = 1;
1726 status = generate_hash(data, datasize, context, sha256hash, sha1hash);
1727 in_protocol = 0;
1728
1729 return status;
1730}
1731
1732static EFI_STATUS shim_read_header(void *data, unsigned int datasize,
1733 PE_COFF_LOADER_IMAGE_CONTEXT *context)
1734{
1735 EFI_STATUS status;
1736
1737 in_protocol = 1;
1738 status = read_header(data, datasize, context);
1739 in_protocol = 0;
f4b24734
MG
1740
1741 return status;
1742}
1743
0aee67a8
MG
1744/*
1745 * Load and run an EFI executable
1746 */
1395a991 1747EFI_STATUS start_image(EFI_HANDLE image_handle, CHAR16 *ImagePath)
e235c85a 1748{
1395a991 1749 EFI_GUID loaded_image_protocol = LOADED_IMAGE_PROTOCOL;
e235c85a 1750 EFI_STATUS efi_status;
1395a991 1751 EFI_LOADED_IMAGE *li, li_bak;
d8e330b9
MG
1752 CHAR16 *PathName = NULL;
1753 void *sourcebuffer = NULL;
d98242e3 1754 UINT64 sourcesize = 0;
e235c85a
GCPL
1755 void *data = NULL;
1756 int datasize;
1757
0aee67a8
MG
1758 /*
1759 * We need to refer to the loaded image protocol on the running
1760 * binary in order to find our path
1761 */
1395a991 1762 efi_status = uefi_call_wrapper(BS->HandleProtocol, 3, image_handle,
24a602b6 1763 &loaded_image_protocol, (void **)&li);
1395a991
GCPL
1764
1765 if (efi_status != EFI_SUCCESS) {
4bfb13d8 1766 perror(L"Unable to init protocol\n");
1395a991
GCPL
1767 return efi_status;
1768 }
1769
0aee67a8
MG
1770 /*
1771 * Build a new path from the existing one plus the executable name
1772 */
78aaad30 1773 efi_status = generate_path(li, ImagePath, &PathName);
1395a991
GCPL
1774
1775 if (efi_status != EFI_SUCCESS) {
4bfb13d8 1776 perror(L"Unable to generate path %s: %r\n", ImagePath, efi_status);
1395a991
GCPL
1777 goto done;
1778 }
1779
f500a874 1780 if (findNetboot(li->DeviceHandle)) {
d8e330b9
MG
1781 efi_status = parseNetbootinfo(image_handle);
1782 if (efi_status != EFI_SUCCESS) {
4bfb13d8 1783 perror(L"Netboot parsing failed: %r\n", efi_status);
d8e330b9
MG
1784 return EFI_PROTOCOL_ERROR;
1785 }
1786 efi_status = FetchNetbootimage(image_handle, &sourcebuffer,
1787 &sourcesize);
1788 if (efi_status != EFI_SUCCESS) {
4bfb13d8 1789 perror(L"Unable to fetch TFTP image: %r\n", efi_status);
d8e330b9
MG
1790 return efi_status;
1791 }
1792 data = sourcebuffer;
1793 datasize = sourcesize;
3d79bcb2
GCPL
1794#if defined(ENABLE_HTTPBOOT)
1795 } else if (find_httpboot(li->DeviceHandle)) {
1796 efi_status = httpboot_fetch_buffer (image_handle, &sourcebuffer,
1797 &sourcesize);
1798 if (efi_status != EFI_SUCCESS) {
1799 perror(L"Unable to fetch HTTP image: %r\n", efi_status);
1800 return efi_status;
1801 }
1802 data = sourcebuffer;
1803 datasize = sourcesize;
1804#endif
d8e330b9 1805 } else {
821eca49
MG
1806 /*
1807 * Read the new executable off disk
1808 */
d8e330b9 1809 efi_status = load_image(li, &data, &datasize, PathName);
e235c85a 1810
d8e330b9 1811 if (efi_status != EFI_SUCCESS) {
4bfb13d8 1812 perror(L"Failed to load image %s: %r\n", PathName, efi_status);
d8e330b9
MG
1813 goto done;
1814 }
e235c85a
GCPL
1815 }
1816
22b58f24 1817 /* Measure the binary into the TPM */
d00ea555
PJ
1818 tpm_log_event((EFI_PHYSICAL_ADDRESS)(UINTN)data, datasize,
1819 9, (CHAR8 *)"Second stage bootloader");
22b58f24 1820
0aee67a8
MG
1821 /*
1822 * We need to modify the loaded image protocol entry before running
1823 * the new binary, so back it up
1824 */
e235c85a
GCPL
1825 CopyMem(&li_bak, li, sizeof(li_bak));
1826
0aee67a8
MG
1827 /*
1828 * Verify and, if appropriate, relocate and execute the executable
1829 */
e235c85a
GCPL
1830 efi_status = handle_image(data, datasize, li);
1831
1832 if (efi_status != EFI_SUCCESS) {
4bfb13d8 1833 perror(L"Failed to load image: %r\n", efi_status);
e235c85a
GCPL
1834 CopyMem(li, &li_bak, sizeof(li_bak));
1835 goto done;
1836 }
1837
39df41ce
PJ
1838 loader_is_participating = 0;
1839
0aee67a8
MG
1840 /*
1841 * The binary is trusted and relocated. Run it
1842 */
9913079b 1843 efi_status = uefi_call_wrapper(entry_point, 2, image_handle, systab);
e235c85a 1844
0aee67a8
MG
1845 /*
1846 * Restore our original loaded image values
1847 */
e235c85a
GCPL
1848 CopyMem(li, &li_bak, sizeof(li_bak));
1849done:
9913079b
MG
1850 if (PathName)
1851 FreePool(PathName);
1852
1853 if (data)
1854 FreePool(data);
1855
e235c85a
GCPL
1856 return efi_status;
1857}
1858
0aee67a8
MG
1859/*
1860 * Load and run grub. If that fails because grub isn't trusted, load and
1861 * run MokManager.
1862 */
03685963 1863EFI_STATUS init_grub(EFI_HANDLE image_handle)
b2fe1780
MG
1864{
1865 EFI_STATUS efi_status;
0b394a94 1866 int use_fb = should_use_fallback(image_handle);
f4b24734 1867
0b394a94 1868 efi_status = start_image(image_handle, use_fb ? FALLBACK :second_stage);
9f2c83e6
PJ
1869 if (efi_status == EFI_SECURITY_VIOLATION ||
1870 efi_status == EFI_ACCESS_DENIED) {
6d50f87a 1871 efi_status = start_image(image_handle, MOK_MANAGER);
0b394a94
PJ
1872 if (efi_status != EFI_SUCCESS) {
1873 Print(L"start_image() returned %r\n", efi_status);
1874 uefi_call_wrapper(BS->Stall, 1, 2000000);
1875 return efi_status;
1876 }
1877
1878 efi_status = start_image(image_handle,
1879 use_fb ? FALLBACK : second_stage);
1880 }
03685963 1881
f7c34e9b
PJ
1882 if (efi_status != EFI_SUCCESS) {
1883 Print(L"start_image() returned %r\n", efi_status);
1884 uefi_call_wrapper(BS->Stall, 1, 2000000);
1885 }
5195d7d3 1886
03685963
MG
1887 return efi_status;
1888}
1889
22b58f24
MG
1890/*
1891 * Measure some of the MOK variables into the TPM
1892 */
1893EFI_STATUS measure_mok()
1894{
1895 EFI_GUID shim_lock_guid = SHIM_LOCK_GUID;
1896 EFI_STATUS efi_status;
1897 UINT8 *Data = NULL;
1898 UINTN DataSize = 0;
1899
1900 efi_status = get_variable(L"MokList", &Data, &DataSize, shim_lock_guid);
1901 if (efi_status != EFI_SUCCESS)
1902 return efi_status;
1903
d00ea555
PJ
1904 efi_status = tpm_log_event((EFI_PHYSICAL_ADDRESS)(UINTN)Data,
1905 DataSize, 14, (CHAR8 *)"MokList");
22b58f24
MG
1906
1907 FreePool(Data);
1908
1909 if (efi_status != EFI_SUCCESS)
1910 return efi_status;
1911
1912 efi_status = get_variable(L"MokSBState", &Data, &DataSize,
1913 shim_lock_guid);
1914
1915 if (efi_status != EFI_SUCCESS)
1916 return efi_status;
1917
d00ea555
PJ
1918 efi_status = tpm_log_event((EFI_PHYSICAL_ADDRESS)(UINTN)Data,
1919 DataSize, 14, (CHAR8 *)"MokSBState");
22b58f24
MG
1920
1921 FreePool(Data);
1922
1923 return efi_status;
1924}
1925
0aee67a8
MG
1926/*
1927 * Copy the boot-services only MokList variable to the runtime-accessible
1928 * MokListRT variable. It's not marked NV, so the OS can't modify it.
1929 */
ed2ecf86
GCPL
1930EFI_STATUS mirror_mok_list()
1931{
1932 EFI_GUID shim_lock_guid = SHIM_LOCK_GUID;
1933 EFI_STATUS efi_status;
7d602e84 1934 UINT8 *Data = NULL;
ed2ecf86 1935 UINTN DataSize = 0;
b538992d
PJ
1936 void *FullData = NULL;
1937 UINTN FullDataSize = 0;
1938 EFI_SIGNATURE_LIST *CertList = NULL;
1939 EFI_SIGNATURE_DATA *CertData = NULL;
1940 uint8_t *p = NULL;
ed2ecf86 1941
7d602e84 1942 efi_status = get_variable(L"MokList", &Data, &DataSize, shim_lock_guid);
b538992d
PJ
1943 if (efi_status != EFI_SUCCESS)
1944 DataSize = 0;
1945
f1411950
PJ
1946 if (vendor_cert_size) {
1947 FullDataSize = DataSize
1948 + sizeof (*CertList)
1949 + sizeof (EFI_GUID)
1950 + vendor_cert_size
1951 ;
1952 FullData = AllocatePool(FullDataSize);
1953 if (!FullData) {
1954 perror(L"Failed to allocate space for MokListRT\n");
1955 return EFI_OUT_OF_RESOURCES;
1956 }
1957 p = FullData;
ed2ecf86 1958
f1411950
PJ
1959 if (efi_status == EFI_SUCCESS && DataSize > 0) {
1960 CopyMem(p, Data, DataSize);
1961 p += DataSize;
1962 }
1963 CertList = (EFI_SIGNATURE_LIST *)p;
1964 p += sizeof (*CertList);
1965 CertData = (EFI_SIGNATURE_DATA *)p;
1966 p += sizeof (EFI_GUID);
1967
1968 CertList->SignatureType = EFI_CERT_X509_GUID;
1969 CertList->SignatureListSize = vendor_cert_size
1970 + sizeof (*CertList)
1971 + sizeof (*CertData)
1972 -1;
1973 CertList->SignatureHeaderSize = 0;
1974 CertList->SignatureSize = vendor_cert_size + sizeof (EFI_GUID);
1975
1976 CertData->SignatureOwner = SHIM_LOCK_GUID;
1977 CopyMem(p, vendor_cert, vendor_cert_size);
1978 } else {
1979 FullDataSize = DataSize;
1980 FullData = Data;
ed2ecf86
GCPL
1981 }
1982
1983 efi_status = uefi_call_wrapper(RT->SetVariable, 5, L"MokListRT",
1984 &shim_lock_guid,
1985 EFI_VARIABLE_BOOTSERVICE_ACCESS
1986 | EFI_VARIABLE_RUNTIME_ACCESS,
b538992d 1987 FullDataSize, FullData);
ed2ecf86 1988 if (efi_status != EFI_SUCCESS) {
4bfb13d8 1989 perror(L"Failed to set MokListRT: %r\n", efi_status);
ed2ecf86
GCPL
1990 }
1991
ed2ecf86
GCPL
1992 return efi_status;
1993}
1994
9a811c32
GCPL
1995/*
1996 * Copy the boot-services only MokListX variable to the runtime-accessible
1997 * MokListXRT variable. It's not marked NV, so the OS can't modify it.
1998 */
1999EFI_STATUS mirror_mok_list_x()
2000{
2001 EFI_GUID shim_lock_guid = SHIM_LOCK_GUID;
2002 EFI_STATUS efi_status;
2003 UINT8 *Data = NULL;
2004 UINTN DataSize = 0;
2005
2006 efi_status = get_variable(L"MokListX", &Data, &DataSize, shim_lock_guid);
2007 if (efi_status != EFI_SUCCESS)
2008 return efi_status;
2009
2010 efi_status = uefi_call_wrapper(RT->SetVariable, 5, L"MokListXRT",
2011 &shim_lock_guid,
2012 EFI_VARIABLE_BOOTSERVICE_ACCESS
2013 | EFI_VARIABLE_RUNTIME_ACCESS,
2014 DataSize, Data);
2015 if (efi_status != EFI_SUCCESS) {
2016 console_error(L"Failed to set MokListRT", efi_status);
2017 }
2018
2019 return efi_status;
2020}
2021
8f1bd605
MTL
2022/*
2023 * Copy the boot-services only MokSBState variable to the runtime-accessible
2024 * MokSBStateRT variable. It's not marked NV, so the OS can't modify it.
2025 */
2026EFI_STATUS mirror_mok_sb_state()
2027{
2028 EFI_GUID shim_lock_guid = SHIM_LOCK_GUID;
2029 EFI_STATUS efi_status;
2030 UINT8 *Data = NULL;
2031 UINTN DataSize = 0;
2032
2033 efi_status = get_variable(L"MokSBState", &Data, &DataSize, shim_lock_guid);
07bda585
IH
2034 if (efi_status == EFI_SUCCESS) {
2035 UINT8 *Data_RT = NULL;
2036 UINTN DataSize_RT = 0;
2037
2038 efi_status = get_variable(L"MokSBStateRT", &Data_RT,
2039 &DataSize_RT, shim_lock_guid);
2040 if (efi_status == EFI_SUCCESS) {
2041 efi_status = uefi_call_wrapper(RT->SetVariable, 5,
2042 L"MokSBStateRT",
2043 &shim_lock_guid,
2044 EFI_VARIABLE_BOOTSERVICE_ACCESS
2045 | EFI_VARIABLE_RUNTIME_ACCESS
2046 | EFI_VARIABLE_NON_VOLATILE,
2047 0, NULL);
2048 }
8f1bd605 2049
07bda585
IH
2050 efi_status = uefi_call_wrapper(RT->SetVariable, 5,
2051 L"MokSBStateRT",
2052 &shim_lock_guid,
2053 EFI_VARIABLE_BOOTSERVICE_ACCESS
2054 | EFI_VARIABLE_RUNTIME_ACCESS,
2055 DataSize, Data);
2056 if (efi_status != EFI_SUCCESS) {
2057 console_error(L"Failed to set MokSBStateRT", efi_status);
2058 }
8f1bd605 2059 }
8f1bd605
MTL
2060 return efi_status;
2061}
2062
0aee67a8
MG
2063/*
2064 * Check if a variable exists
2065 */
4e3721a0 2066static BOOLEAN check_var(CHAR16 *varname)
0d7c3dbd
GCPL
2067{
2068 EFI_STATUS efi_status;
5f00e44f 2069 EFI_GUID shim_lock_guid = SHIM_LOCK_GUID;
5d4b6ba0 2070 UINTN size = sizeof(UINT32);
801c0faa 2071 UINT32 MokVar;
5f00e44f
GCPL
2072 UINT32 attributes;
2073
4e3721a0 2074 efi_status = uefi_call_wrapper(RT->GetVariable, 5, varname,
5d4b6ba0 2075 &shim_lock_guid, &attributes,
4e3721a0 2076 &size, (void *)&MokVar);
5f00e44f 2077
4e3721a0
MG
2078 if (efi_status == EFI_SUCCESS || efi_status == EFI_BUFFER_TOO_SMALL)
2079 return TRUE;
0d7c3dbd 2080
4e3721a0
MG
2081 return FALSE;
2082}
0d7c3dbd 2083
0aee67a8
MG
2084/*
2085 * If the OS has set any of these variables we need to drop into MOK and
2086 * handle them appropriately
2087 */
4e3721a0
MG
2088EFI_STATUS check_mok_request(EFI_HANDLE image_handle)
2089{
2090 EFI_STATUS efi_status;
0d7c3dbd 2091
4e3721a0 2092 if (check_var(L"MokNew") || check_var(L"MokSB") ||
990dcdb6 2093 check_var(L"MokPW") || check_var(L"MokAuth") ||
64c5066c 2094 check_var(L"MokDel") || check_var(L"MokDB") ||
7cb3ee92
GCPL
2095 check_var(L"MokXNew") || check_var(L"MokXDel") ||
2096 check_var(L"MokXAuth")) {
c1faa462 2097 efi_status = start_image(image_handle, MOK_MANAGER);
0d7c3dbd 2098
c1faa462 2099 if (efi_status != EFI_SUCCESS) {
4bfb13d8 2100 perror(L"Failed to start MokManager: %r\n", efi_status);
c1faa462
MG
2101 return efi_status;
2102 }
0d7c3dbd 2103 }
0d7c3dbd 2104
c1faa462 2105 return EFI_SUCCESS;
0d7c3dbd
GCPL
2106}
2107
0aee67a8
MG
2108/*
2109 * Verify that MokSBState is valid, and if appropriate set insecure mode
2110 */
7127b1ab
MG
2111static EFI_STATUS check_mok_sb (void)
2112{
2113 EFI_GUID shim_lock_guid = SHIM_LOCK_GUID;
2114 EFI_STATUS status = EFI_SUCCESS;
e5f16114
GCPL
2115 UINT8 MokSBState;
2116 UINTN MokSBStateSize = sizeof(MokSBState);
7127b1ab
MG
2117 UINT32 attributes;
2118
d95b24bd 2119 user_insecure_mode = 0;
46002a3e
PJ
2120 ignore_db = 0;
2121
e5f16114
GCPL
2122 status = uefi_call_wrapper(RT->GetVariable, 5, L"MokSBState", &shim_lock_guid,
2123 &attributes, &MokSBStateSize, &MokSBState);
7127b1ab 2124 if (status != EFI_SUCCESS)
6ebf9b87 2125 return EFI_SECURITY_VIOLATION;
7127b1ab 2126
0aee67a8
MG
2127 /*
2128 * Delete and ignore the variable if it's been set from or could be
2129 * modified by the OS
2130 */
7127b1ab 2131 if (attributes & EFI_VARIABLE_RUNTIME_ACCESS) {
4bfb13d8 2132 perror(L"MokSBState is compromised! Clearing it\n");
7127b1ab 2133 if (LibDeleteVariable(L"MokSBState", &shim_lock_guid) != EFI_SUCCESS) {
4bfb13d8 2134 perror(L"Failed to erase MokSBState\n");
7127b1ab 2135 }
6ebf9b87 2136 status = EFI_SECURITY_VIOLATION;
7127b1ab 2137 } else {
e5f16114 2138 if (MokSBState == 1) {
d95b24bd 2139 user_insecure_mode = 1;
7127b1ab
MG
2140 }
2141 }
2142
2143 return status;
0d7c3dbd
GCPL
2144}
2145
ef0383d0
JB
2146/*
2147 * Verify that MokDBState is valid, and if appropriate set ignore db mode
2148 */
2149
2150static EFI_STATUS check_mok_db (void)
2151{
2152 EFI_GUID shim_lock_guid = SHIM_LOCK_GUID;
2153 EFI_STATUS status = EFI_SUCCESS;
e5f16114 2154 UINT8 MokDBState;
9249fc28 2155 UINTN MokDBStateSize = sizeof(MokDBState);
ef0383d0
JB
2156 UINT32 attributes;
2157
e5f16114
GCPL
2158 status = uefi_call_wrapper(RT->GetVariable, 5, L"MokDBState", &shim_lock_guid,
2159 &attributes, &MokDBStateSize, &MokDBState);
ef0383d0 2160 if (status != EFI_SUCCESS)
6ebf9b87 2161 return EFI_SECURITY_VIOLATION;
ef0383d0
JB
2162
2163 ignore_db = 0;
2164
2165 /*
2166 * Delete and ignore the variable if it's been set from or could be
2167 * modified by the OS
2168 */
2169 if (attributes & EFI_VARIABLE_RUNTIME_ACCESS) {
4bfb13d8 2170 perror(L"MokDBState is compromised! Clearing it\n");
ef0383d0 2171 if (LibDeleteVariable(L"MokDBState", &shim_lock_guid) != EFI_SUCCESS) {
4bfb13d8 2172 perror(L"Failed to erase MokDBState\n");
ef0383d0 2173 }
6ebf9b87 2174 status = EFI_SECURITY_VIOLATION;
ef0383d0 2175 } else {
e5f16114 2176 if (MokDBState == 1) {
ef0383d0
JB
2177 ignore_db = 1;
2178 }
2179 }
2180
ef0383d0
JB
2181 return status;
2182}
2183
2184static EFI_STATUS mok_ignore_db()
2185{
2186 EFI_GUID shim_lock_guid = SHIM_LOCK_GUID;
2187 EFI_STATUS efi_status = EFI_SUCCESS;
2188 UINT8 Data = 1;
2189 UINTN DataSize = sizeof(UINT8);
2190
2191 check_mok_db();
2192
2193 if (ignore_db) {
2194 efi_status = uefi_call_wrapper(RT->SetVariable, 5, L"MokIgnoreDB",
2195 &shim_lock_guid,
2196 EFI_VARIABLE_BOOTSERVICE_ACCESS
2197 | EFI_VARIABLE_RUNTIME_ACCESS,
2198 DataSize, (void *)&Data);
2199 if (efi_status != EFI_SUCCESS) {
4bfb13d8 2200 perror(L"Failed to set MokIgnoreDB: %r\n", efi_status);
ef0383d0
JB
2201 }
2202 }
2203
2204 return efi_status;
2205
2206}
2207
3322257e
PJ
2208EFI_GUID bds_guid = { 0x8108ac4e, 0x9f11, 0x4d59, { 0x85, 0x0e, 0xe2, 0x1a, 0x52, 0x2c, 0x59, 0xb2 } };
2209
2210static inline EFI_STATUS
2211get_load_option_optional_data(UINT8 *data, UINTN data_size,
2212 UINT8 **od, UINTN *ods)
2213{
2214 /*
2215 * If it's not at least Attributes + FilePathListLength +
2216 * Description=L"" + 0x7fff0400 (EndEntrireDevicePath), it can't
2217 * be valid.
2218 */
2219 if (data_size < (sizeof(UINT32) + sizeof(UINT16) + 2 + 4))
2220 return EFI_INVALID_PARAMETER;
2221
2222 UINT8 *cur = data + sizeof(UINT32);
2223 UINT16 fplistlen = *(UINT16 *)cur;
2224 /*
2225 * If there's not enough space for the file path list and the
2226 * smallest possible description (L""), it's not valid.
2227 */
2228 if (fplistlen > data_size - (sizeof(UINT32) + 2 + 4))
2229 return EFI_INVALID_PARAMETER;
2230
2231 cur += sizeof(UINT16);
2232 UINTN limit = data_size - (cur - data) - fplistlen;
2233 UINTN i;
2234 for (i = 0; i < limit ; i++) {
2235 /* If the description isn't valid UCS2-LE, it's not valid. */
2236 if (i % 2 != 0) {
2237 if (cur[i] != 0)
2238 return EFI_INVALID_PARAMETER;
2239 } else if (cur[i] == 0) {
2240 /* we've found the end */
2241 i++;
2242 if (i >= limit || cur[i] != 0)
2243 return EFI_INVALID_PARAMETER;
2244 break;
2245 }
2246 }
2247 i++;
2248 if (i > limit)
2249 return EFI_INVALID_PARAMETER;
2250
2251 /*
2252 * If i is limit, we know the rest of this is the FilePathList and
2253 * there's no optional data. So just bail now.
2254 */
2255 if (i == limit) {
2256 *od = NULL;
2257 *ods = 0;
2258 return EFI_SUCCESS;
2259 }
2260
2261 cur += i;
2262 limit -= i;
2263 limit += fplistlen;
2264 i = 0;
2265 while (limit - i >= 4) {
2266 struct {
2267 UINT8 type;
2268 UINT8 subtype;
2269 UINT16 len;
2270 } dp = {
2271 .type = cur[i],
2272 .subtype = cur[i+1],
2273 /*
2274 * it's a little endian UINT16, but we're not
2275 * guaranteed alignment is sane, so we can't just
2276 * typecast it directly.
2277 */
2278 .len = (cur[i+3] << 8) | cur[i+2],
2279 };
2280
2281 /*
2282 * We haven't found an EndEntire, so this has to be a valid
2283 * EFI_DEVICE_PATH in order for the data to be valid. That
2284 * means it has to fit, and it can't be smaller than 4 bytes.
2285 */
2286 if (dp.len < 4 || dp.len > limit)
2287 return EFI_INVALID_PARAMETER;
2288
2289 /*
2290 * see if this is an EndEntire node...
2291 */
2292 if (dp.type == 0x7f && dp.subtype == 0xff) {
2293 /*
2294 * if we've found the EndEntire node, it must be 4
2295 * bytes
2296 */
2297 if (dp.len != 4)
2298 return EFI_INVALID_PARAMETER;
2299
2300 i += dp.len;
2301 break;
2302 }
2303
2304 /*
2305 * It's just some random DP node; skip it.
2306 */
2307 i += dp.len;
2308 }
2309 if (i != fplistlen)
2310 return EFI_INVALID_PARAMETER;
2311
2312 /*
2313 * if there's any space left, it's "optional data"
2314 */
2315 *od = cur + i;
2316 *ods = limit - i;
2317 return EFI_SUCCESS;
2318}
2319
7a44b29e
PJ
2320static int is_our_path(EFI_LOADED_IMAGE *li, CHAR16 *path, UINTN len)
2321{
2322 CHAR16 *dppath = NULL;
2323 int ret = 1;
2324
2325 dppath = DevicePathToStr(li->FilePath);
2326 if (!dppath)
2327 return 0;
2328
2329 Print(L"dppath: %s\n", dppath);
2330 Print(L"path: %s\n", path);
2331 if (StrnCaseCmp(dppath, path, len))
2332 ret = 0;
2333
2334 FreePool(dppath);
2335 return ret;
2336}
2337
14d4b8e5
GCPL
2338/*
2339 * Check the load options to specify the second stage loader
2340 */
2341EFI_STATUS set_second_stage (EFI_HANDLE image_handle)
2342{
2343 EFI_STATUS status;
29f3c91d 2344 EFI_LOADED_IMAGE *li = NULL;
3322257e 2345 CHAR16 *start = NULL;
5495694c 2346 int remaining_size = 0;
9754732c 2347 CHAR16 *loader_str = NULL;
3322257e
PJ
2348 UINTN loader_len = 0;
2349 unsigned int i;
14d4b8e5
GCPL
2350
2351 second_stage = DEFAULT_LOADER;
2352 load_options = NULL;
2353 load_options_size = 0;
2354
2355 status = uefi_call_wrapper(BS->HandleProtocol, 3, image_handle,
2356 &LoadedImageProtocol, (void **) &li);
2357 if (status != EFI_SUCCESS) {
4bfb13d8 2358 perror (L"Failed to get load options: %r\n", status);
14d4b8e5
GCPL
2359 return status;
2360 }
2361
3322257e
PJ
2362 /* So, load options are a giant pain in the ass. If we're invoked
2363 * from the EFI shell, we get something like this:
2364
236500000000 5c 00 45 00 36 00 49 00 5c 00 66 00 65 00 64 00 |\.E.F.I.\.f.e.d.|
236600000010 6f 00 72 00 61 00 5c 00 73 00 68 00 69 00 6d 00 |o.r.a.\.s.h.i.m.|
236700000020 78 00 36 00 34 00 2e 00 64 00 66 00 69 00 20 00 |x.6.4...e.f.i. .|
236800000030 5c 00 45 00 46 00 49 00 5c 00 66 00 65 00 64 00 |\.E.F.I.\.f.e.d.|
236900000040 6f 00 72 00 61 00 5c 00 66 00 77 00 75 00 70 00 |o.r.a.\.f.w.u.p.|
237000000050 64 00 61 00 74 00 65 00 2e 00 65 00 66 00 20 00 |d.a.t.e.e.f.i. .|
237100000060 00 00 66 00 73 00 30 00 3a 00 5c 00 00 00 |..f.s.0.:.\...|
2372
2373 *
2374 * which is just some paths rammed together separated by a UCS-2 NUL.
2375 * But if we're invoked from BDS, we get something more like:
2376 *
2377
237800000000 01 00 00 00 62 00 4c 00 69 00 6e 00 75 00 78 00 |....b.L.i.n.u.x.|
237900000010 20 00 46 00 69 00 72 00 6d 00 77 00 61 00 72 00 | .F.i.r.m.w.a.r.|
238000000020 65 00 20 00 55 00 70 00 64 00 61 00 74 00 65 00 |e. .U.p.d.a.t.e.|
238100000030 72 00 00 00 40 01 2a 00 01 00 00 00 00 08 00 00 |r.....*.........|
238200000040 00 00 00 00 00 40 06 00 00 00 00 00 1a 9e 55 bf |.....@........U.|
238300000050 04 57 f2 4f b4 4a ed 26 4a 40 6a 94 02 02 04 04 |.W.O.:.&J@j.....|
238400000060 34 00 5c 00 45 00 46 00 49 00 5c 00 66 00 65 00 |4.\.E.F.I.f.e.d.|
238500000070 64 00 6f 00 72 00 61 00 5c 00 73 00 68 00 69 00 |o.r.a.\.s.h.i.m.|
238600000080 6d 00 78 00 36 00 34 00 2e 00 65 00 66 00 69 00 |x.6.4...e.f.i...|
238700000090 00 00 7f ff 40 00 20 00 5c 00 66 00 77 00 75 00 |...... .\.f.w.u.|
2388000000a0 70 00 78 00 36 00 34 00 2e 00 65 00 66 00 69 00 |p.x.6.4...e.f.i.|
2389000000b0 00 00 |..|
2390
2391 *
2392 * which is clearly an EFI_LOAD_OPTION filled in halfway reasonably.
2393 * In short, the UEFI shell is still a useless piece of junk.
085d56c4
IH
2394 *
2395 * But then on some versions of BDS, we get:
2396
239700000000 5c 00 66 00 77 00 75 00 70 00 78 00 36 00 34 00 |\.f.w.u.p.x.6.4.|
239800000010 2e 00 65 00 66 00 69 00 00 00 |..e.f.i...|
23990000001a
2400
2401 * which as you can see is one perfectly normal UCS2-EL string
2402 * containing the load option from the Boot#### variable.
2403 *
2404 * We also sometimes find a guid or partial guid at the end, because
2405 * BDS will add that, but we ignore that here.
3322257e
PJ
2406 */
2407
2408 /*
2409 * In either case, we've got to have at least a UCS2 NUL...
2410 */
2411 if (li->LoadOptionsSize < 2)
14d4b8e5 2412 return EFI_BAD_BUFFER_SIZE;
3322257e
PJ
2413
2414 /*
2415 * Some awesome versions of BDS will add entries for Linux. On top
2416 * of that, some versions of BDS will "tag" any Boot#### entries they
2417 * create by putting a GUID at the very end of the optional data in
2418 * the EFI_LOAD_OPTIONS, thus screwing things up for everybody who
2419 * tries to actually *use* the optional data for anything. Why they
2420 * did this instead of adding a flag to the spec to /say/ it's
2421 * created by BDS, I do not know. For shame.
2422 *
2423 * Anyway, just nerf that out from the start. It's always just
2424 * garbage at the end.
2425 */
2426 if (li->LoadOptionsSize > 16) {
2427 if (CompareGuid((EFI_GUID *)(li->LoadOptions
2428 + (li->LoadOptionsSize - 16)),
2429 &bds_guid) == 0)
2430 li->LoadOptionsSize -= 16;
14d4b8e5
GCPL
2431 }
2432
9754732c 2433 /*
3322257e
PJ
2434 * Check and see if this is just a list of strings. If it's an
2435 * EFI_LOAD_OPTION, it'll be 0, since we know EndEntire device path
2436 * won't pass muster as UCS2-LE.
2437 *
2438 * If there are 3 strings, we're launched from the shell most likely,
2439 * But we actually only care about the second one.
9754732c 2440 */
3322257e
PJ
2441 UINTN strings = count_ucs2_strings(li->LoadOptions,
2442 li->LoadOptionsSize);
2443 /*
2444 * If it's not string data, try it as an EFI_LOAD_OPTION.
2445 */
2446 if (strings == 0) {
2447 /*
2448 * We at least didn't find /enough/ strings. See if it works
2449 * as an EFI_LOAD_OPTION.
2450 */
2451 status = get_load_option_optional_data(li->LoadOptions,
2452 li->LoadOptionsSize,
2453 (UINT8 **)&start,
2454 &loader_len);
2455 if (status != EFI_SUCCESS)
2456 return EFI_SUCCESS;
2457
2458 remaining_size = 0;
2459 } else if (strings >= 2) {
2460 /*
2461 * UEFI shell copies the whole line of the command into
2462 * LoadOptions. We ignore the string before the first L' ',
2463 * i.e. the name of this program.
2464 * Counting by two bytes is safe, because we know the size is
2465 * compatible with a UCS2-LE string.
2466 */
2467 UINT8 *cur = li->LoadOptions;
2468 for (i = 0; i < li->LoadOptionsSize - 2; i += 2) {
2469 CHAR16 c = (cur[i+1] << 8) | cur[i];
2470 if (c == L' ') {
2471 start = (CHAR16 *)&cur[i+2];
2472 remaining_size = li->LoadOptionsSize - i - 2;
2473 break;
2474 }
14d4b8e5 2475 }
14d4b8e5 2476
3322257e
PJ
2477 if (!start || remaining_size <= 0 || start[0] == L'\0')
2478 return EFI_SUCCESS;
2cead91e 2479
3322257e
PJ
2480 for (i = 0; start[i] != '\0'; i++) {
2481 if (start[i] == L' ')
2482 start[i] = L'\0';
2483 if (start[i] == L'\0') {
2484 loader_len = 2 * i + 2;
2485 break;
2486 }
2487 }
2488 if (loader_len)
2489 remaining_size -= loader_len;
085d56c4
IH
2490 } else {
2491 /* only find one string */
2492 start = li->LoadOptions;
2493 loader_len = li->LoadOptionsSize;
9754732c
GCPL
2494 }
2495
2496 /*
3322257e
PJ
2497 * Just to be sure all that math is right...
2498 */
2499 if (loader_len % 2 != 0)
2500 return EFI_INVALID_PARAMETER;
2501
2502 strings = count_ucs2_strings((UINT8 *)start, loader_len);
2503 if (strings < 1)
2504 return EFI_SUCCESS;
2505
7a44b29e
PJ
2506 /*
2507 * And then I found a version of BDS that gives us our own path in
2508 * LoadOptions:
2509
251077162C58 5c 00 45 00 46 00 49 00 |\.E.F.I.|
251177162C60 5c 00 42 00 4f 00 4f 00 54 00 5c 00 42 00 4f 00 |\.B.O.O.T.\.B.O.|
251277162C70 4f 00 54 00 58 00 36 00 34 00 2e 00 45 00 46 00 |O.T.X.6.4...E.F.|
251377162C80 49 00 00 00 |I...|
2514
2515 * which is just cruel... So yeah, just don't use it.
2516 */
2517 if (strings == 1 && is_our_path(li, start, loader_len))
2518 return EFI_SUCCESS;
2519
3322257e
PJ
2520 /*
2521 * Set up the name of the alternative loader and the LoadOptions for
9754732c
GCPL
2522 * the loader
2523 */
2524 if (loader_len > 0) {
3322257e 2525 loader_str = AllocatePool(loader_len);
9754732c 2526 if (!loader_str) {
4bfb13d8 2527 perror(L"Failed to allocate loader string\n");
9754732c
GCPL
2528 return EFI_OUT_OF_RESOURCES;
2529 }
3322257e
PJ
2530
2531 for (i = 0; i < loader_len / 2; i++)
9754732c 2532 loader_str[i] = start[i];
3322257e 2533 loader_str[loader_len/2-1] = L'\0';
9754732c
GCPL
2534
2535 second_stage = loader_str;
3322257e 2536 load_options = remaining_size ? start + loader_len : NULL;
14d4b8e5
GCPL
2537 load_options_size = remaining_size;
2538 }
2539
2540 return EFI_SUCCESS;
2541}
2542
06495f69
PJ
2543static SHIM_LOCK shim_lock_interface;
2544static EFI_HANDLE shim_lock_handle;
2545
2546EFI_STATUS
2547install_shim_protocols(void)
2548{
2549 EFI_GUID shim_lock_guid = SHIM_LOCK_GUID;
2550 EFI_STATUS efi_status;
5195d7d3
PJ
2551
2552 if (!secure_mode())
2553 return EFI_SUCCESS;
2554
06495f69
PJ
2555 /*
2556 * Install the protocol
2557 */
2558 efi_status = uefi_call_wrapper(BS->InstallProtocolInterface, 4,
2559 &shim_lock_handle, &shim_lock_guid,
2560 EFI_NATIVE_INTERFACE, &shim_lock_interface);
2561 if (EFI_ERROR(efi_status)) {
2562 console_error(L"Could not install security protocol",
2563 efi_status);
2564 return efi_status;
2565 }
2566
2567#if defined(OVERRIDE_SECURITY_POLICY)
2568 /*
2569 * Install the security protocol hook
2570 */
2571 security_policy_install(shim_verify);
2572#endif
2573
2574 return EFI_SUCCESS;
2575}
2576
2577void
2578uninstall_shim_protocols(void)
03685963
MG
2579{
2580 EFI_GUID shim_lock_guid = SHIM_LOCK_GUID;
5195d7d3
PJ
2581
2582 if (!secure_mode())
2583 return;
2584
06495f69
PJ
2585#if defined(OVERRIDE_SECURITY_POLICY)
2586 /*
2587 * Clean up the security protocol hook
2588 */
2589 security_policy_uninstall();
2590#endif
2591
2592 /*
2593 * If we're back here then clean everything up before exiting
2594 */
2595 uefi_call_wrapper(BS->UninstallProtocolInterface, 3, shim_lock_handle,
2596 &shim_lock_guid, &shim_lock_interface);
2597}
2598
7ad94952
PJ
2599EFI_STATUS
2600shim_init(void)
2601{
2602 EFI_STATUS status = EFI_SUCCESS;
2603 setup_console(1);
2604 setup_verbosity();
2605 dprinta(shim_version);
2606
2607 /* Set the second stage loader */
29f3c91d 2608 set_second_stage (global_image_handle);
7ad94952
PJ
2609
2610 if (secure_mode()) {
2611 if (vendor_cert_size || vendor_dbx_size) {
2612 /*
2613 * If shim includes its own certificates then ensure
2614 * that anything it boots has performed some
2615 * validation of the next image.
2616 */
2617 hook_system_services(systab);
2618 loader_is_participating = 0;
2619 }
2620
2621 hook_exit(systab);
2622
2623 status = install_shim_protocols();
2624 }
2625 return status;
2626}
2627
2628void
2629shim_fini(void)
2630{
2631 if (secure_mode()) {
2632 /*
2633 * Remove our protocols
2634 */
2635 uninstall_shim_protocols();
2636
2637 /*
2638 * Remove our hooks from system services.
2639 */
2640 unhook_system_services();
2641 unhook_exit();
2642 }
2643
2644 /*
2645 * Free the space allocated for the alternative 2nd stage loader
2646 */
2647 if (load_options_size > 0 && second_stage)
2648 FreePool(second_stage);
2649
2650 setup_console(0);
2651}
2652
a0319607
PJ
2653extern EFI_STATUS
2654efi_main(EFI_HANDLE passed_image_handle, EFI_SYSTEM_TABLE *passed_systab);
2655
2656static void
2657__attribute__((__optimize__("0")))
2658debug_hook(void)
2659{
2660 EFI_GUID guid = SHIM_LOCK_GUID;
2661 UINT8 *data = NULL;
2662 UINTN dataSize = 0;
2663 EFI_STATUS efi_status;
70ce2c42 2664 volatile register UINTN x = 0;
a0319607
PJ
2665 extern char _text, _data;
2666
2667 if (x)
2668 return;
2669
2670 efi_status = get_variable(L"SHIM_DEBUG", &data, &dataSize, guid);
2671 if (EFI_ERROR(efi_status)) {
2672 return;
2673 }
2674
70ce2c42 2675 Print(L"add-symbol-file "DEBUGDIR
6f040920 2676 L"shim" EFI_ARCH L".efi.debug 0x%08x -s .data 0x%08x\n", &_text,
a0319607
PJ
2677 &_data);
2678
2679 Print(L"Pausing for debugger attachment.\n");
70ce2c42
PJ
2680 Print(L"To disable this, remove the EFI variable SHIM_DEBUG-%g .\n",
2681 &guid);
a0319607 2682 x = 1;
70ce2c42
PJ
2683 while (x++) {
2684 /* Make this so it can't /totally/ DoS us. */
a0319607 2685#if defined(__x86_64__) || defined(__i386__) || defined(__i686__)
e22b8561 2686 if (x > 4294967294ULL)
70ce2c42 2687 break;
a0319607
PJ
2688 __asm__ __volatile__("pause");
2689#elif defined(__aarch64__)
70ce2c42
PJ
2690 if (x > 1000)
2691 break;
a0319607
PJ
2692 __asm__ __volatile__("wfi");
2693#else
70ce2c42
PJ
2694 if (x > 12000)
2695 break;
2696 uefi_call_wrapper(BS->Stall, 1, 5000);
a0319607
PJ
2697#endif
2698 }
2699 x = 1;
2700}
2701
2702EFI_STATUS
2703efi_main (EFI_HANDLE passed_image_handle, EFI_SYSTEM_TABLE *passed_systab)
06495f69 2704{
49ebaa4b 2705 EFI_STATUS efi_status;
29f3c91d 2706 EFI_HANDLE image_handle;
03685963 2707
39df41ce
PJ
2708 verification_method = VERIFIED_BY_NOTHING;
2709
02388bcd
PJ
2710 vendor_cert_size = cert_table.vendor_cert_size;
2711 vendor_dbx_size = cert_table.vendor_dbx_size;
2712 vendor_cert = (UINT8 *)&cert_table + cert_table.vendor_cert_offset;
2713 vendor_dbx = (UINT8 *)&cert_table + cert_table.vendor_dbx_offset;
2714
0aee67a8
MG
2715 /*
2716 * Set up the shim lock protocol so that grub and MokManager can
2717 * call back in and use shim functions
2718 */
03685963 2719 shim_lock_interface.Verify = shim_verify;
4bfb13d8
GCPL
2720 shim_lock_interface.Hash = shim_hash;
2721 shim_lock_interface.Context = shim_read_header;
03685963
MG
2722
2723 systab = passed_systab;
29f3c91d 2724 image_handle = global_image_handle = passed_image_handle;
03685963 2725
0aee67a8
MG
2726 /*
2727 * Ensure that gnu-efi functions are available
2728 */
03685963
MG
2729 InitializeLib(image_handle, systab);
2730
a0319607
PJ
2731 /*
2732 * if SHIM_DEBUG is set, wait for a debugger to attach.
2733 */
2734 debug_hook();
2735
22b58f24
MG
2736 /*
2737 * Measure the MOK variables
2738 */
2739 efi_status = measure_mok();
2740 if (efi_status != EFI_SUCCESS && efi_status != EFI_NOT_FOUND) {
2741 Print(L"Something has gone seriously wrong: %r\n", efi_status);
2742 Print(L"Shim was unable to measure state into the TPM\n");
2743 systab->BootServices->Stall(5000000);
2744 systab->RuntimeServices->ResetSystem(EfiResetShutdown,
2745 EFI_SECURITY_VIOLATION,
2746 0, NULL);
2747 }
2748
0aee67a8
MG
2749 /*
2750 * Check whether the user has configured the system to run in
2751 * insecure mode
2752 */
7127b1ab
MG
2753 check_mok_sb();
2754
7ad94952
PJ
2755 efi_status = shim_init();
2756 if (EFI_ERROR(efi_status)) {
2757 Print(L"Something has gone seriously wrong: %r\n", efi_status);
2758 Print(L"shim cannot continue, sorry.\n");
cf5f75fa
PJ
2759 uefi_call_wrapper(BS->Stall, 1, 5000000);
2760 uefi_call_wrapper(systab->RuntimeServices->ResetSystem, 4,
2761 EfiResetShutdown, EFI_SECURITY_VIOLATION,
2762 0, NULL);
7ad94952
PJ
2763 }
2764
0aee67a8
MG
2765 /*
2766 * Tell the user that we're in insecure mode if necessary
2767 */
d95b24bd 2768 if (user_insecure_mode) {
7127b1ab
MG
2769 Print(L"Booting in insecure mode\n");
2770 uefi_call_wrapper(BS->Stall, 1, 2000000);
2771 }
2772
0aee67a8
MG
2773 /*
2774 * Enter MokManager if necessary
2775 */
0d7c3dbd
GCPL
2776 efi_status = check_mok_request(image_handle);
2777
0aee67a8 2778 /*
7ad94952
PJ
2779 * Copy the MOK list to a runtime variable so the kernel can
2780 * make use of it
0aee67a8 2781 */
ed2ecf86
GCPL
2782 efi_status = mirror_mok_list();
2783
9a811c32
GCPL
2784 efi_status = mirror_mok_list_x();
2785
8f1bd605
MTL
2786 /*
2787 * Copy the MOK SB State to a runtime variable so the kernel can
2788 * make use of it
2789 */
2790 efi_status = mirror_mok_sb_state();
2791
ef0383d0 2792 /*
7ad94952
PJ
2793 * Create the runtime MokIgnoreDB variable so the kernel can
2794 * make use of it
ef0383d0
JB
2795 */
2796 efi_status = mok_ignore_db();
2797
0aee67a8
MG
2798 /*
2799 * Hand over control to the second stage bootloader
2800 */
49ebaa4b
MG
2801 efi_status = init_grub(image_handle);
2802
7ad94952 2803 shim_fini();
49ebaa4b 2804 return efi_status;
b2fe1780 2805}