]> git.proxmox.com Git - efi-boot-shim.git/blame - shim.c
Don't print things on the screen by default when everything works.
[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"
3df68c18 41#include "signature.h"
1c595706 42#include "netboot.h"
ef8c9962 43#include "shim_cert.h"
6e1bd3dc 44#include "ucs2.h"
b2fe1780 45
09e2c939 46#define DEFAULT_LOADER L"\\grub.efi"
6d6b0221 47#define FALLBACK L"\\fallback.efi"
4b34567d 48#define MOK_MANAGER L"\\MokManager.efi"
f898777d 49
7f055335
MG
50static EFI_SYSTEM_TABLE *systab;
51static EFI_STATUS (EFIAPI *entry_point) (EFI_HANDLE image_handle, EFI_SYSTEM_TABLE *system_table);
52
09e2c939
GCPL
53static CHAR16 *second_stage;
54static void *load_options;
55static UINT32 load_options_size;
e75294e5 56static UINT8 verbose;
09e2c939 57
f898777d
MG
58/*
59 * The vendor certificate used for validating the second stage loader
60 */
8518b8cc
PJ
61extern UINT8 vendor_cert[];
62extern UINT32 vendor_cert_size;
92888645 63extern UINT8 vendor_dbx[];
5f0a358b 64extern UINT32 vendor_dbx_size;
b2fe1780 65
c13fc2f7
MG
66#define EFI_IMAGE_SECURITY_DATABASE_GUID { 0xd719b2cb, 0x3d3a, 0x4596, { 0xa3, 0xbc, 0xda, 0xd0, 0x0e, 0x67, 0x65, 0x6f }}
67
9eaadb0d
MG
68static UINT8 insecure_mode;
69
c16548d0
MG
70typedef enum {
71 DATA_FOUND,
72 DATA_NOT_FOUND,
73 VAR_NOT_FOUND
74} CHECK_STATUS;
75
13422973
GCPL
76typedef struct {
77 UINT32 MokSize;
78 UINT8 *Mok;
79} MokListNode;
80
31d3bd05 81static EFI_STATUS get_variable (CHAR16 *name, EFI_GUID guid, UINT32 *attributes,
3df68c18 82 UINTN *size, void **buffer)
5bc80cec
MG
83{
84 EFI_STATUS efi_status;
c13fc2f7 85 char allocate = !(*size);
5bc80cec
MG
86
87 efi_status = uefi_call_wrapper(RT->GetVariable, 5, name, &guid,
31d3bd05 88 attributes, size, buffer);
5bc80cec 89
c13fc2f7 90 if (efi_status != EFI_BUFFER_TOO_SMALL || !allocate) {
5bc80cec 91 return efi_status;
c13fc2f7 92 }
5bc80cec 93
cbe21407 94 *buffer = AllocatePool(*size);
5bc80cec
MG
95
96 if (!*buffer) {
97 Print(L"Unable to allocate variable buffer\n");
98 return EFI_OUT_OF_RESOURCES;
99 }
100
101 efi_status = uefi_call_wrapper(RT->GetVariable, 5, name, &guid,
31d3bd05 102 attributes, size, *buffer);
5bc80cec
MG
103
104 return efi_status;
105}
106
f898777d
MG
107/*
108 * Perform basic bounds checking of the intra-image pointers
109 */
110static void *ImageAddress (void *image, int size, unsigned int address)
b2fe1780 111{
f898777d
MG
112 if (address > size)
113 return NULL;
9d56c38f 114
f898777d
MG
115 return image + address;
116}
9d56c38f 117
f898777d
MG
118/*
119 * Perform the actual relocation
120 */
7db60bd8
MG
121static EFI_STATUS relocate_coff (PE_COFF_LOADER_IMAGE_CONTEXT *context,
122 void *data)
f898777d
MG
123{
124 EFI_IMAGE_BASE_RELOCATION *RelocBase, *RelocBaseEnd;
125 UINT64 Adjust;
126 UINT16 *Reloc, *RelocEnd;
127 char *Fixup, *FixupBase, *FixupData = NULL;
128 UINT16 *Fixup16;
129 UINT32 *Fixup32;
130 UINT64 *Fixup64;
131 int size = context->ImageSize;
7db60bd8 132 void *ImageEnd = (char *)data + size;
9d56c38f 133
7db60bd8 134 context->PEHdr->Pe32Plus.OptionalHeader.ImageBase = (UINT64)data;
7f055335 135
f898777d
MG
136 if (context->NumberOfRvaAndSizes <= EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC) {
137 Print(L"Image has no relocation entry\n");
138 return EFI_UNSUPPORTED;
7f055335
MG
139 }
140
7db60bd8
MG
141 RelocBase = ImageAddress(data, size, context->RelocDir->VirtualAddress);
142 RelocBaseEnd = ImageAddress(data, size, context->RelocDir->VirtualAddress + context->RelocDir->Size - 1);
9d56c38f 143
f898777d
MG
144 if (!RelocBase || !RelocBaseEnd) {
145 Print(L"Reloc table overflows binary\n");
146 return EFI_UNSUPPORTED;
9d56c38f
MG
147 }
148
7db60bd8 149 Adjust = (UINT64)data - context->ImageAddress;
9d56c38f 150
f898777d
MG
151 while (RelocBase < RelocBaseEnd) {
152 Reloc = (UINT16 *) ((char *) RelocBase + sizeof (EFI_IMAGE_BASE_RELOCATION));
153 RelocEnd = (UINT16 *) ((char *) RelocBase + RelocBase->SizeOfBlock);
9d56c38f 154
7db60bd8 155 if ((void *)RelocEnd < data || (void *)RelocEnd > ImageEnd) {
f898777d
MG
156 Print(L"Reloc entry overflows binary\n");
157 return EFI_UNSUPPORTED;
9d56c38f
MG
158 }
159
7db60bd8 160 FixupBase = ImageAddress(data, size, RelocBase->VirtualAddress);
f898777d
MG
161 if (!FixupBase) {
162 Print(L"Invalid fixupbase\n");
163 return EFI_UNSUPPORTED;
9d56c38f 164 }
9d56c38f 165
f898777d
MG
166 while (Reloc < RelocEnd) {
167 Fixup = FixupBase + (*Reloc & 0xFFF);
168 switch ((*Reloc) >> 12) {
169 case EFI_IMAGE_REL_BASED_ABSOLUTE:
170 break;
9d56c38f 171
f898777d
MG
172 case EFI_IMAGE_REL_BASED_HIGH:
173 Fixup16 = (UINT16 *) Fixup;
174 *Fixup16 = (UINT16) (*Fixup16 + ((UINT16) ((UINT32) Adjust >> 16)));
175 if (FixupData != NULL) {
176 *(UINT16 *) FixupData = *Fixup16;
177 FixupData = FixupData + sizeof (UINT16);
178 }
179 break;
9d56c38f 180
f898777d
MG
181 case EFI_IMAGE_REL_BASED_LOW:
182 Fixup16 = (UINT16 *) Fixup;
183 *Fixup16 = (UINT16) (*Fixup16 + (UINT16) Adjust);
184 if (FixupData != NULL) {
185 *(UINT16 *) FixupData = *Fixup16;
186 FixupData = FixupData + sizeof (UINT16);
187 }
188 break;
b2fe1780 189
f898777d
MG
190 case EFI_IMAGE_REL_BASED_HIGHLOW:
191 Fixup32 = (UINT32 *) Fixup;
192 *Fixup32 = *Fixup32 + (UINT32) Adjust;
193 if (FixupData != NULL) {
194 FixupData = ALIGN_POINTER (FixupData, sizeof (UINT32));
195 *(UINT32 *)FixupData = *Fixup32;
196 FixupData = FixupData + sizeof (UINT32);
197 }
198 break;
b2fe1780 199
f898777d
MG
200 case EFI_IMAGE_REL_BASED_DIR64:
201 Fixup64 = (UINT64 *) Fixup;
202 *Fixup64 = *Fixup64 + (UINT64) Adjust;
203 if (FixupData != NULL) {
204 FixupData = ALIGN_POINTER (FixupData, sizeof(UINT64));
205 *(UINT64 *)(FixupData) = *Fixup64;
206 FixupData = FixupData + sizeof(UINT64);
207 }
208 break;
b2fe1780 209
f898777d
MG
210 default:
211 Print(L"Unknown relocation\n");
212 return EFI_UNSUPPORTED;
213 }
214 Reloc += 1;
0e6b0195 215 }
f898777d 216 RelocBase = (EFI_IMAGE_BASE_RELOCATION *) RelocEnd;
7f055335 217 }
b2fe1780
MG
218
219 return EFI_SUCCESS;
220}
221
5f0a358b
PJ
222static CHECK_STATUS check_db_cert_in_ram(EFI_SIGNATURE_LIST *CertList,
223 UINTN dbsize,
224 WIN_CERTIFICATE_EFI_PKCS *data,
225 UINT8 *hash)
3df68c18 226{
3df68c18 227 EFI_SIGNATURE_DATA *Cert;
c16548d0 228 UINTN CertCount, Index;
c13fc2f7 229 BOOLEAN IsFound = FALSE;
c16548d0
MG
230 EFI_GUID CertType = EfiCertX509Guid;
231
c16548d0 232 while ((dbsize > 0) && (dbsize >= CertList->SignatureListSize)) {
c13fc2f7 233 if (CompareGuid (&CertList->SignatureType, &CertType) == 0) {
c16548d0
MG
234 CertCount = (CertList->SignatureListSize - CertList->SignatureHeaderSize) / CertList->SignatureSize;
235 Cert = (EFI_SIGNATURE_DATA *) ((UINT8 *) CertList + sizeof (EFI_SIGNATURE_LIST) + CertList->SignatureHeaderSize);
236 for (Index = 0; Index < CertCount; Index++) {
237 IsFound = AuthenticodeVerify (data->CertData,
238 data->Hdr.dwLength - sizeof(data->Hdr),
239 Cert->SignatureData,
240 CertList->SignatureSize,
241 hash, SHA256_DIGEST_SIZE);
7430b901
PJ
242 if (IsFound)
243 break;
201574d1
MG
244
245 Cert = (EFI_SIGNATURE_DATA *) ((UINT8 *) Cert + CertList->SignatureSize);
c16548d0
MG
246 }
247
c16548d0
MG
248 }
249
058c0368
MG
250 if (IsFound)
251 break;
252
c16548d0
MG
253 dbsize -= CertList->SignatureListSize;
254 CertList = (EFI_SIGNATURE_LIST *) ((UINT8 *) CertList + CertList->SignatureListSize);
255 }
256
c16548d0
MG
257 if (IsFound)
258 return DATA_FOUND;
259
260 return DATA_NOT_FOUND;
261}
262
5f0a358b
PJ
263static CHECK_STATUS check_db_cert(CHAR16 *dbname, EFI_GUID guid,
264 WIN_CERTIFICATE_EFI_PKCS *data, UINT8 *hash)
c16548d0 265{
5f0a358b 266 CHECK_STATUS rc;
c16548d0 267 EFI_STATUS efi_status;
c16548d0 268 EFI_SIGNATURE_LIST *CertList;
c16548d0 269 UINTN dbsize = 0;
31d3bd05 270 UINT32 attributes;
3df68c18 271 void *db;
3df68c18 272
0a6565c5 273 efi_status = get_variable(dbname, guid, &attributes, &dbsize, &db);
3df68c18 274
5f0a358b 275 if (efi_status != EFI_SUCCESS)
c16548d0 276 return VAR_NOT_FOUND;
3df68c18
MG
277
278 CertList = db;
279
5f0a358b
PJ
280 rc = check_db_cert_in_ram(CertList, dbsize, data, hash);
281
282 FreePool(db);
283
284 return rc;
285}
286
20f6cde6
MG
287/*
288 * Check a hash against an EFI_SIGNATURE_LIST in a buffer
289 */
5f0a358b
PJ
290static CHECK_STATUS check_db_hash_in_ram(EFI_SIGNATURE_LIST *CertList,
291 UINTN dbsize, UINT8 *data,
292 int SignatureSize, EFI_GUID CertType)
293{
294 EFI_SIGNATURE_DATA *Cert;
295 UINTN CertCount, Index;
296 BOOLEAN IsFound = FALSE;
297
c16548d0 298 while ((dbsize > 0) && (dbsize >= CertList->SignatureListSize)) {
3df68c18
MG
299 CertCount = (CertList->SignatureListSize - CertList->SignatureHeaderSize) / CertList->SignatureSize;
300 Cert = (EFI_SIGNATURE_DATA *) ((UINT8 *) CertList + sizeof (EFI_SIGNATURE_LIST) + CertList->SignatureHeaderSize);
c13fc2f7 301 if (CompareGuid(&CertList->SignatureType, &CertType) == 0) {
3df68c18 302 for (Index = 0; Index < CertCount; Index++) {
c16548d0 303 if (CompareMem (Cert->SignatureData, data, SignatureSize) == 0) {
3df68c18
MG
304 //
305 // Find the signature in database.
306 //
307 IsFound = TRUE;
308 break;
309 }
310
311 Cert = (EFI_SIGNATURE_DATA *) ((UINT8 *) Cert + CertList->SignatureSize);
312 }
313 if (IsFound) {
314 break;
315 }
316 }
317
c16548d0 318 dbsize -= CertList->SignatureListSize;
3df68c18
MG
319 CertList = (EFI_SIGNATURE_LIST *) ((UINT8 *) CertList + CertList->SignatureListSize);
320 }
321
3df68c18 322 if (IsFound)
c16548d0
MG
323 return DATA_FOUND;
324
325 return DATA_NOT_FOUND;
326}
327
20f6cde6
MG
328/*
329 * Check a hash against an EFI_SIGNATURE_LIST in a UEFI variable
330 */
5f0a358b
PJ
331static CHECK_STATUS check_db_hash(CHAR16 *dbname, EFI_GUID guid, UINT8 *data,
332 int SignatureSize, EFI_GUID CertType)
333{
334 EFI_STATUS efi_status;
335 EFI_SIGNATURE_LIST *CertList;
336 UINT32 attributes;
337 UINTN dbsize = 0;
338 void *db;
339
340 efi_status = get_variable(dbname, guid, &attributes, &dbsize, &db);
341
342 if (efi_status != EFI_SUCCESS) {
343 return VAR_NOT_FOUND;
344 }
345
346 CertList = db;
347
348 CHECK_STATUS rc = check_db_hash_in_ram(CertList, dbsize, data,
349 SignatureSize, CertType);
350 FreePool(db);
351 return rc;
352
353}
354
20f6cde6
MG
355/*
356 * Check whether the binary signature or hash are present in dbx or the
357 * built-in blacklist
358 */
ce6a5748
MG
359static EFI_STATUS check_blacklist (WIN_CERTIFICATE_EFI_PKCS *cert,
360 UINT8 *sha256hash, UINT8 *sha1hash)
c16548d0 361{
0a6565c5 362 EFI_GUID secure_var = EFI_IMAGE_SECURITY_DATABASE_GUID;
92888645 363 EFI_SIGNATURE_LIST *dbx = (EFI_SIGNATURE_LIST *)vendor_dbx;
0a6565c5 364
92888645 365 if (check_db_hash_in_ram(dbx, vendor_dbx_size, sha256hash,
5f0a358b 366 SHA256_DIGEST_SIZE, EfiHashSha256Guid) ==
8b7685b2 367 DATA_FOUND)
5f0a358b 368 return EFI_ACCESS_DENIED;
92888645 369 if (check_db_hash_in_ram(dbx, vendor_dbx_size, sha1hash,
5f0a358b 370 SHA1_DIGEST_SIZE, EfiHashSha1Guid) ==
8b7685b2 371 DATA_FOUND)
5f0a358b 372 return EFI_ACCESS_DENIED;
92888645 373 if (check_db_cert_in_ram(dbx, vendor_dbx_size, cert,
8b7685b2 374 sha256hash) == DATA_FOUND)
5f0a358b
PJ
375 return EFI_ACCESS_DENIED;
376
0a6565c5 377 if (check_db_hash(L"dbx", secure_var, sha256hash, SHA256_DIGEST_SIZE,
ce6a5748 378 EfiHashSha256Guid) == DATA_FOUND)
c16548d0 379 return EFI_ACCESS_DENIED;
0a6565c5 380 if (check_db_hash(L"dbx", secure_var, sha1hash, SHA1_DIGEST_SIZE,
ce6a5748
MG
381 EfiHashSha1Guid) == DATA_FOUND)
382 return EFI_ACCESS_DENIED;
0a6565c5 383 if (check_db_cert(L"dbx", secure_var, cert, sha256hash) == DATA_FOUND)
3df68c18
MG
384 return EFI_ACCESS_DENIED;
385
386 return EFI_SUCCESS;
387}
388
20f6cde6
MG
389/*
390 * Check whether the binary signature or hash are present in db or MokList
391 */
ce6a5748
MG
392static EFI_STATUS check_whitelist (WIN_CERTIFICATE_EFI_PKCS *cert,
393 UINT8 *sha256hash, UINT8 *sha1hash)
b2058cf8 394{
0a6565c5
MG
395 EFI_GUID secure_var = EFI_IMAGE_SECURITY_DATABASE_GUID;
396 EFI_GUID shim_var = SHIM_LOCK_GUID;
397
398 if (check_db_hash(L"db", secure_var, sha256hash, SHA256_DIGEST_SIZE,
ce6a5748
MG
399 EfiHashSha256Guid) == DATA_FOUND)
400 return EFI_SUCCESS;
0a6565c5 401 if (check_db_hash(L"db", secure_var, sha1hash, SHA1_DIGEST_SIZE,
ce6a5748 402 EfiHashSha1Guid) == DATA_FOUND)
b2058cf8 403 return EFI_SUCCESS;
0a6565c5
MG
404 if (check_db_hash(L"MokList", shim_var, sha256hash, SHA256_DIGEST_SIZE,
405 EfiHashSha256Guid) == DATA_FOUND)
406 return EFI_SUCCESS;
407 if (check_db_cert(L"db", secure_var, cert, sha256hash) == DATA_FOUND)
408 return EFI_SUCCESS;
409 if (check_db_cert(L"MokList", shim_var, cert, sha256hash) == DATA_FOUND)
b2058cf8
MG
410 return EFI_SUCCESS;
411
412 return EFI_ACCESS_DENIED;
413}
414
6279b58e
MG
415/*
416 * Check whether we're in Secure Boot and user mode
417 */
418
419static BOOLEAN secure_mode (void)
420{
421 EFI_STATUS status;
422 EFI_GUID global_var = EFI_GLOBAL_VARIABLE;
423 UINTN charsize = sizeof(char);
424 UINT8 sb, setupmode;
31d3bd05 425 UINT32 attributes;
6279b58e 426
9eaadb0d
MG
427 if (insecure_mode)
428 return FALSE;
429
31d3bd05
GCPL
430 status = get_variable(L"SecureBoot", global_var, &attributes, &charsize,
431 (void *)&sb);
6279b58e
MG
432
433 /* FIXME - more paranoia here? */
434 if (status != EFI_SUCCESS || sb != 1) {
e75294e5
PJ
435 if (verbose)
436 Print(L"Secure boot not enabled\n");
6279b58e
MG
437 return FALSE;
438 }
439
31d3bd05
GCPL
440 status = get_variable(L"SetupMode", global_var, &attributes, &charsize,
441 (void *)&setupmode);
6279b58e
MG
442
443 if (status == EFI_SUCCESS && setupmode == 1) {
e75294e5
PJ
444 if (verbose)
445 Print(L"Platform is in setup mode\n");
6279b58e
MG
446 return FALSE;
447 }
448
449 return TRUE;
450}
451
f898777d 452/*
f394b22e 453 * Calculate the SHA1 and SHA256 hashes of a binary
f898777d 454 */
f394b22e
MG
455
456static EFI_STATUS generate_hash (char *data, int datasize,
457 PE_COFF_LOADER_IMAGE_CONTEXT *context,
458 UINT8 *sha256hash, UINT8 *sha1hash)
459
7f055335 460{
ce6a5748 461 unsigned int sha256ctxsize, sha1ctxsize;
f394b22e 462 unsigned int size = datasize;
ce6a5748 463 void *sha256ctx = NULL, *sha1ctx = NULL;
7f055335
MG
464 char *hashbase;
465 unsigned int hashsize;
7f055335 466 unsigned int SumOfBytesHashed, SumOfSectionBytes;
3df68c18 467 unsigned int index, pos;
7f055335 468 EFI_IMAGE_SECTION_HEADER *Section;
0db1af8a 469 EFI_IMAGE_SECTION_HEADER *SectionHeader = NULL;
7f055335 470 EFI_IMAGE_SECTION_HEADER *SectionCache;
f394b22e 471 EFI_STATUS status = EFI_SUCCESS;
7f055335 472
ce6a5748
MG
473 sha256ctxsize = Sha256GetContextSize();
474 sha256ctx = AllocatePool(sha256ctxsize);
475
476 sha1ctxsize = Sha1GetContextSize();
477 sha1ctx = AllocatePool(sha1ctxsize);
7f055335 478
ce6a5748 479 if (!sha256ctx || !sha1ctx) {
7f055335
MG
480 Print(L"Unable to allocate memory for hash context\n");
481 return EFI_OUT_OF_RESOURCES;
482 }
483
ce6a5748 484 if (!Sha256Init(sha256ctx) || !Sha1Init(sha1ctx)) {
7f055335
MG
485 Print(L"Unable to initialise hash\n");
486 status = EFI_OUT_OF_RESOURCES;
487 goto done;
488 }
489
490 /* Hash start to checksum */
7db60bd8 491 hashbase = data;
7f055335
MG
492 hashsize = (char *)&context->PEHdr->Pe32.OptionalHeader.CheckSum -
493 hashbase;
494
ce6a5748
MG
495 if (!(Sha256Update(sha256ctx, hashbase, hashsize)) ||
496 !(Sha1Update(sha1ctx, hashbase, hashsize))) {
7f055335
MG
497 Print(L"Unable to generate hash\n");
498 status = EFI_OUT_OF_RESOURCES;
499 goto done;
500 }
501
502 /* Hash post-checksum to start of certificate table */
503 hashbase = (char *)&context->PEHdr->Pe32.OptionalHeader.CheckSum +
504 sizeof (int);
505 hashsize = (char *)context->SecDir - hashbase;
506
ce6a5748
MG
507 if (!(Sha256Update(sha256ctx, hashbase, hashsize)) ||
508 !(Sha1Update(sha1ctx, hashbase, hashsize))) {
7f055335
MG
509 Print(L"Unable to generate hash\n");
510 status = EFI_OUT_OF_RESOURCES;
511 goto done;
512 }
513
514 /* Hash end of certificate table to end of image header */
515 hashbase = (char *) &context->PEHdr->Pe32Plus.OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY + 1];
516 hashsize = context->PEHdr->Pe32Plus.OptionalHeader.SizeOfHeaders -
7db60bd8 517 (int) ((char *) (&context->PEHdr->Pe32Plus.OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY + 1]) - data);
0db1af8a 518
ce6a5748
MG
519 if (!(Sha256Update(sha256ctx, hashbase, hashsize)) ||
520 !(Sha1Update(sha1ctx, hashbase, hashsize))) {
7f055335
MG
521 Print(L"Unable to generate hash\n");
522 status = EFI_OUT_OF_RESOURCES;
523 goto done;
524 }
525
f898777d 526 /* Sort sections */
7f055335
MG
527 SumOfBytesHashed = context->PEHdr->Pe32Plus.OptionalHeader.SizeOfHeaders;
528
529 Section = (EFI_IMAGE_SECTION_HEADER *) (
530 (char *)context->PEHdr + sizeof (UINT32) +
531 sizeof (EFI_IMAGE_FILE_HEADER) +
532 context->PEHdr->Pe32.FileHeader.SizeOfOptionalHeader
533 );
534
535 SectionCache = Section;
536
537 for (index = 0, SumOfSectionBytes = 0; index < context->PEHdr->Pe32.FileHeader.NumberOfSections; index++, SectionCache++) {
538 SumOfSectionBytes += SectionCache->SizeOfRawData;
539 }
540
7db60bd8 541 if (SumOfSectionBytes >= datasize) {
7f055335
MG
542 Print(L"Malformed binary: %x %x\n", SumOfSectionBytes, size);
543 status = EFI_INVALID_PARAMETER;
544 goto done;
545 }
546
547 SectionHeader = (EFI_IMAGE_SECTION_HEADER *) AllocateZeroPool (sizeof (EFI_IMAGE_SECTION_HEADER) * context->PEHdr->Pe32.FileHeader.NumberOfSections);
548 if (SectionHeader == NULL) {
549 Print(L"Unable to allocate section header\n");
550 status = EFI_OUT_OF_RESOURCES;
551 goto done;
552 }
553
554 /* Sort the section headers */
555 for (index = 0; index < context->PEHdr->Pe32.FileHeader.NumberOfSections; index++) {
556 pos = index;
557 while ((pos > 0) && (Section->PointerToRawData < SectionHeader[pos - 1].PointerToRawData)) {
558 CopyMem (&SectionHeader[pos], &SectionHeader[pos - 1], sizeof (EFI_IMAGE_SECTION_HEADER));
559 pos--;
560 }
561 CopyMem (&SectionHeader[pos], Section, sizeof (EFI_IMAGE_SECTION_HEADER));
562 Section += 1;
563 }
564
565 /* Hash the sections */
566 for (index = 0; index < context->PEHdr->Pe32.FileHeader.NumberOfSections; index++) {
567 Section = &SectionHeader[index];
568 if (Section->SizeOfRawData == 0) {
569 continue;
570 }
7db60bd8 571 hashbase = ImageAddress(data, size, Section->PointerToRawData);
7f055335
MG
572 hashsize = (unsigned int) Section->SizeOfRawData;
573
f898777d
MG
574 if (!hashbase) {
575 Print(L"Malformed section header\n");
cbe21407
MG
576 status = EFI_INVALID_PARAMETER;
577 goto done;
f898777d
MG
578 }
579
ce6a5748
MG
580 if (!(Sha256Update(sha256ctx, hashbase, hashsize)) ||
581 !(Sha1Update(sha1ctx, hashbase, hashsize))) {
7f055335
MG
582 Print(L"Unable to generate hash\n");
583 status = EFI_OUT_OF_RESOURCES;
584 goto done;
585 }
586 SumOfBytesHashed += Section->SizeOfRawData;
587 }
588
589 /* Hash all remaining data */
590 if (size > SumOfBytesHashed) {
7db60bd8 591 hashbase = data + SumOfBytesHashed;
7f055335
MG
592 hashsize = (unsigned int)(
593 size -
594 context->PEHdr->Pe32Plus.OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY].Size -
595 SumOfBytesHashed);
596
ce6a5748
MG
597 if (!(Sha256Update(sha256ctx, hashbase, hashsize)) ||
598 !(Sha1Update(sha1ctx, hashbase, hashsize))) {
7f055335
MG
599 Print(L"Unable to generate hash\n");
600 status = EFI_OUT_OF_RESOURCES;
601 goto done;
602 }
603 }
604
ce6a5748
MG
605 if (!(Sha256Final(sha256ctx, sha256hash)) ||
606 !(Sha1Final(sha1ctx, sha1hash))) {
7f055335
MG
607 Print(L"Unable to finalise hash\n");
608 status = EFI_OUT_OF_RESOURCES;
609 goto done;
610 }
611
f394b22e
MG
612done:
613 if (SectionHeader)
614 FreePool(SectionHeader);
615 if (sha1ctx)
616 FreePool(sha1ctx);
617 if (sha256ctx)
618 FreePool(sha256ctx);
619
620 return status;
621}
622
20f6cde6
MG
623/*
624 * Ensure that the MOK database hasn't been set or modified from an OS
625 */
0a6565c5
MG
626static EFI_STATUS verify_mok (void) {
627 EFI_GUID shim_lock_guid = SHIM_LOCK_GUID;
628 EFI_STATUS status = EFI_SUCCESS;
629 void *MokListData = NULL;
630 UINTN MokListDataSize = 0;
631 UINT32 attributes;
632
633 status = get_variable(L"MokList", shim_lock_guid, &attributes,
634 &MokListDataSize, &MokListData);
635
636 if (attributes & EFI_VARIABLE_RUNTIME_ACCESS) {
637 Print(L"MokList is compromised!\nErase all keys in MokList!\n");
638 if (LibDeleteVariable(L"MokList", &shim_lock_guid) != EFI_SUCCESS) {
639 Print(L"Failed to erase MokList\n");
640 }
641 status = EFI_ACCESS_DENIED;
642 return status;
643 }
644
645 return EFI_SUCCESS;
646}
647
f394b22e
MG
648/*
649 * Check that the signature is valid and matches the binary
650 */
651static EFI_STATUS verify_buffer (char *data, int datasize,
0a6565c5 652 PE_COFF_LOADER_IMAGE_CONTEXT *context)
f394b22e 653{
f394b22e
MG
654 UINT8 sha256hash[SHA256_DIGEST_SIZE];
655 UINT8 sha1hash[SHA1_DIGEST_SIZE];
656 EFI_STATUS status = EFI_ACCESS_DENIED;
657 WIN_CERTIFICATE_EFI_PKCS *cert;
f394b22e
MG
658 unsigned int size = datasize;
659
832e5161
MG
660 if (context->SecDir->Size == 0) {
661 Print(L"Empty security header\n");
662 return EFI_INVALID_PARAMETER;
663 }
664
f394b22e
MG
665 cert = ImageAddress (data, size, context->SecDir->VirtualAddress);
666
667 if (!cert) {
668 Print(L"Certificate located outside the image\n");
669 return EFI_INVALID_PARAMETER;
670 }
671
672 if (cert->Hdr.wCertificateType != WIN_CERT_TYPE_PKCS_SIGNED_DATA) {
673 Print(L"Unsupported certificate type %x\n",
674 cert->Hdr.wCertificateType);
675 return EFI_UNSUPPORTED;
676 }
677
678 status = generate_hash(data, datasize, context, sha256hash, sha1hash);
679
680 if (status != EFI_SUCCESS)
681 return status;
682
20f6cde6
MG
683 /*
684 * Check that the MOK database hasn't been modified
685 */
0a6565c5
MG
686 verify_mok();
687
20f6cde6
MG
688 /*
689 * Ensure that the binary isn't blacklisted
690 */
ce6a5748 691 status = check_blacklist(cert, sha256hash, sha1hash);
3df68c18
MG
692
693 if (status != EFI_SUCCESS) {
694 Print(L"Binary is blacklisted\n");
f394b22e 695 return status;
3df68c18
MG
696 }
697
20f6cde6
MG
698 /*
699 * Check whether the binary is whitelisted in any of the firmware
700 * databases
701 */
0a6565c5 702 status = check_whitelist(cert, sha256hash, sha1hash);
b2058cf8 703
0a6565c5 704 if (status == EFI_SUCCESS) {
e75294e5
PJ
705 if (verbose)
706 Print(L"Binary is whitelisted\n");
0a6565c5 707 return status;
b2058cf8
MG
708 }
709
ef8c9962
MG
710 /*
711 * Check against the shim build key
712 */
713 if (AuthenticodeVerify(cert->CertData,
714 context->SecDir->Size - sizeof(cert->Hdr),
715 shim_cert, sizeof(shim_cert), sha256hash,
716 SHA256_DIGEST_SIZE)) {
717 status = EFI_SUCCESS;
e75294e5
PJ
718 if (verbose)
719 Print(L"Binary is verified by the vendor certificate\n");
ef8c9962
MG
720 return status;
721 }
722
723
20f6cde6
MG
724 /*
725 * And finally, check against shim's built-in key
726 */
13422973
GCPL
727 if (AuthenticodeVerify(cert->CertData,
728 context->SecDir->Size - sizeof(cert->Hdr),
ce6a5748 729 vendor_cert, vendor_cert_size, sha256hash,
13422973
GCPL
730 SHA256_DIGEST_SIZE)) {
731 status = EFI_SUCCESS;
e75294e5
PJ
732 if (verbose)
733 Print(L"Binary is verified by the vendor certificate\n");
f394b22e 734 return status;
13422973
GCPL
735 }
736
13422973
GCPL
737 Print(L"Invalid signature\n");
738 status = EFI_ACCESS_DENIED;
7f055335 739
f898777d
MG
740 return status;
741}
b2fe1780 742
f898777d
MG
743/*
744 * Read the binary header and grab appropriate information from it
745 */
ce78d2d2 746static EFI_STATUS read_header(void *data, unsigned int datasize,
f898777d
MG
747 PE_COFF_LOADER_IMAGE_CONTEXT *context)
748{
7db60bd8
MG
749 EFI_IMAGE_DOS_HEADER *DosHdr = data;
750 EFI_IMAGE_OPTIONAL_HEADER_UNION *PEHdr = data;
b2fe1780 751
cbe21407
MG
752 if (datasize < sizeof(EFI_IMAGE_DOS_HEADER)) {
753 Print(L"Invalid image\n");
754 return EFI_UNSUPPORTED;
755 }
756
f898777d 757 if (DosHdr->e_magic == EFI_IMAGE_DOS_SIGNATURE)
7db60bd8 758 PEHdr = (EFI_IMAGE_OPTIONAL_HEADER_UNION *)((char *)data + DosHdr->e_lfanew);
b2fe1780 759
cbe21407
MG
760 if ((((UINT8 *)PEHdr - (UINT8 *)data) + sizeof(EFI_IMAGE_OPTIONAL_HEADER_UNION)) > datasize) {
761 Print(L"Invalid image\n");
762 return EFI_UNSUPPORTED;
763 }
764
f898777d
MG
765 if (PEHdr->Te.Signature != EFI_IMAGE_NT_SIGNATURE) {
766 Print(L"Unsupported image type\n");
767 return EFI_UNSUPPORTED;
768 }
b2fe1780 769
f898777d
MG
770 if (PEHdr->Pe32.FileHeader.Characteristics & EFI_IMAGE_FILE_RELOCS_STRIPPED) {
771 Print(L"Unsupported image - Relocations have been stripped\n");
772 return EFI_UNSUPPORTED;
773 }
b2fe1780 774
f898777d
MG
775 if (PEHdr->Pe32.OptionalHeader.Magic != EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC) {
776 Print(L"Only 64-bit images supported\n");
777 return EFI_UNSUPPORTED;
778 }
b2fe1780 779
f898777d
MG
780 context->PEHdr = PEHdr;
781 context->ImageAddress = PEHdr->Pe32Plus.OptionalHeader.ImageBase;
782 context->ImageSize = (UINT64)PEHdr->Pe32Plus.OptionalHeader.SizeOfImage;
783 context->SizeOfHeaders = PEHdr->Pe32Plus.OptionalHeader.SizeOfHeaders;
784 context->EntryPoint = PEHdr->Pe32Plus.OptionalHeader.AddressOfEntryPoint;
785 context->RelocDir = &PEHdr->Pe32Plus.OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC];
786 context->NumberOfRvaAndSizes = PEHdr->Pe32Plus.OptionalHeader.NumberOfRvaAndSizes;
787 context->NumberOfSections = PEHdr->Pe32.FileHeader.NumberOfSections;
788 context->FirstSection = (EFI_IMAGE_SECTION_HEADER *)((char *)PEHdr + PEHdr->Pe32.FileHeader.SizeOfOptionalHeader + sizeof(UINT32) + sizeof(EFI_IMAGE_FILE_HEADER));
789 context->SecDir = (EFI_IMAGE_DATA_DIRECTORY *) &PEHdr->Pe32Plus.OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY];
b2fe1780 790
cbe21407
MG
791 if (context->ImageSize < context->SizeOfHeaders) {
792 Print(L"Invalid image\n");
793 return EFI_UNSUPPORTED;
b2fe1780
MG
794 }
795
cbe21407
MG
796 if (((UINT8 *)context->SecDir - (UINT8 *)data) > (datasize - sizeof(EFI_IMAGE_DATA_DIRECTORY))) {
797 Print(L"Invalid image\n");
798 return EFI_UNSUPPORTED;
799 }
800
ce78d2d2 801 if (context->SecDir->VirtualAddress >= datasize) {
f898777d 802 Print(L"Malformed security header\n");
f898777d
MG
803 return EFI_INVALID_PARAMETER;
804 }
f898777d 805 return EFI_SUCCESS;
b2fe1780
MG
806}
807
f898777d
MG
808/*
809 * Once the image has been loaded it needs to be validated and relocated
810 */
000c565c
GCPL
811static EFI_STATUS handle_image (void *data, unsigned int datasize,
812 EFI_LOADED_IMAGE *li)
b2fe1780
MG
813{
814 EFI_STATUS efi_status;
815 char *buffer;
816 int i, size;
817 EFI_IMAGE_SECTION_HEADER *Section;
0e6b0195 818 char *base, *end;
b2fe1780 819 PE_COFF_LOADER_IMAGE_CONTEXT context;
7f055335 820
20f6cde6
MG
821 /*
822 * The binary header contains relevant context and section pointers
823 */
ce78d2d2 824 efi_status = read_header(data, datasize, &context);
b2fe1780
MG
825 if (efi_status != EFI_SUCCESS) {
826 Print(L"Failed to read header\n");
827 return efi_status;
828 }
829
20f6cde6
MG
830 /*
831 * We only need to verify the binary if we're in secure mode
832 */
6279b58e 833 if (secure_mode ()) {
0a6565c5 834 efi_status = verify_buffer(data, datasize, &context);
7f055335 835
6279b58e
MG
836 if (efi_status != EFI_SUCCESS) {
837 Print(L"Verification failed\n");
838 return efi_status;
839 }
7f055335
MG
840 }
841
b2fe1780
MG
842 buffer = AllocatePool(context.ImageSize);
843
0e6b0195
MG
844 if (!buffer) {
845 Print(L"Failed to allocate image buffer\n");
846 return EFI_OUT_OF_RESOURCES;
847 }
848
7db60bd8 849 CopyMem(buffer, data, context.SizeOfHeaders);
b2fe1780 850
20f6cde6
MG
851 /*
852 * Copy the executable's sections to their desired offsets
853 */
b2fe1780
MG
854 Section = context.FirstSection;
855 for (i = 0; i < context.NumberOfSections; i++) {
856 size = Section->Misc.VirtualSize;
857
858 if (size > Section->SizeOfRawData)
859 size = Section->SizeOfRawData;
860
861 base = ImageAddress (buffer, context.ImageSize, Section->VirtualAddress);
862 end = ImageAddress (buffer, context.ImageSize, Section->VirtualAddress + size - 1);
863
864 if (!base || !end) {
865 Print(L"Invalid section size\n");
866 return EFI_UNSUPPORTED;
867 }
868
b2fe1780 869 if (Section->SizeOfRawData > 0)
7db60bd8 870 CopyMem(base, data + Section->PointerToRawData, size);
b2fe1780
MG
871
872 if (size < Section->Misc.VirtualSize)
873 ZeroMem (base + size, Section->Misc.VirtualSize - size);
874
875 Section += 1;
876 }
877
20f6cde6
MG
878 /*
879 * Run the relocation fixups
880 */
7db60bd8 881 efi_status = relocate_coff(&context, buffer);
b2fe1780
MG
882
883 if (efi_status != EFI_SUCCESS) {
884 Print(L"Relocation failed\n");
0db1af8a 885 FreePool(buffer);
b2fe1780
MG
886 return efi_status;
887 }
888
0e6b0195 889 entry_point = ImageAddress(buffer, context.ImageSize, context.EntryPoint);
20f6cde6
MG
890 /*
891 * grub needs to know its location and size in memory, so fix up
892 * the loaded image protocol values
893 */
5fe882ba
MG
894 li->ImageBase = buffer;
895 li->ImageSize = context.ImageSize;
896
09e2c939
GCPL
897 /* Pass the load options to the second stage loader */
898 li->LoadOptions = load_options;
899 li->LoadOptionsSize = load_options_size;
900
0e6b0195
MG
901 if (!entry_point) {
902 Print(L"Invalid entry point\n");
0db1af8a 903 FreePool(buffer);
0e6b0195
MG
904 return EFI_UNSUPPORTED;
905 }
b2fe1780
MG
906
907 return EFI_SUCCESS;
908}
909
6d6b0221
PJ
910static int
911should_use_fallback(EFI_HANDLE image_handle)
912{
913 EFI_GUID loaded_image_protocol = LOADED_IMAGE_PROTOCOL;
914 EFI_LOADED_IMAGE *li;
6d6b0221
PJ
915 unsigned int pathlen = 0;
916 CHAR16 *bootpath;
917 EFI_FILE_IO_INTERFACE *fio = NULL;
35b0b55b
PJ
918 EFI_FILE *vh;
919 EFI_FILE *fh;
6d6b0221
PJ
920 EFI_STATUS rc;
921
922 rc = uefi_call_wrapper(BS->HandleProtocol, 3, image_handle,
923 &loaded_image_protocol, (void **)&li);
c9d11306
PJ
924 if (EFI_ERROR(rc)) {
925 Print(L"Could not get image for bootx64.efi: %d\n", rc);
6d6b0221 926 return 0;
c9d11306 927 }
6d6b0221 928
2e7fc28d 929 bootpath = DevicePathToStr(li->FilePath);
6d6b0221
PJ
930
931 /* Check the beginning of the string and the end, to avoid
932 * caring about which arch this is. */
933 /* I really don't know why, but sometimes bootpath gives us
934 * L"\\EFI\\BOOT\\/BOOTX64.EFI". So just handle that here...
935 */
936 if (StrnCaseCmp(bootpath, L"\\EFI\\BOOT\\BOOT", 14) &&
937 StrnCaseCmp(bootpath, L"\\EFI\\BOOT\\/BOOT", 15))
938 return 0;
2e7fc28d 939
6d6b0221
PJ
940 pathlen = StrLen(bootpath);
941 if (pathlen < 5 || StrCaseCmp(bootpath + pathlen - 4, L".EFI"))
942 return 0;
943
6d6b0221 944 rc = uefi_call_wrapper(BS->HandleProtocol, 3, li->DeviceHandle,
35b0b55b 945 &FileSystemProtocol, (void **)&fio);
c9d11306
PJ
946 if (EFI_ERROR(rc)) {
947 Print(L"Could not get fio for li->DeviceHandle: %d\n", rc);
6d6b0221 948 return 0;
c9d11306 949 }
6d6b0221
PJ
950
951 rc = uefi_call_wrapper(fio->OpenVolume, 2, fio, &vh);
c9d11306
PJ
952 if (EFI_ERROR(rc)) {
953 Print(L"Could not open fio volume: %d\n", rc);
6d6b0221 954 return 0;
c9d11306 955 }
6d6b0221
PJ
956
957 rc = uefi_call_wrapper(vh->Open, 5, vh, &fh, L"\\EFI\\BOOT" FALLBACK,
5bb3e64e 958 EFI_FILE_MODE_READ, 0);
6d6b0221 959 if (EFI_ERROR(rc)) {
b32a3ce1
PJ
960 /* Do not print the error here - this is an acceptable case
961 * for removable media, where we genuinely don't want
962 * fallback.efi to exist.
963 * Print(L"Could not open \"\\EFI\\BOOT%s\": %d\n", FALLBACK,
964 * rc);
965 */
6d6b0221
PJ
966 uefi_call_wrapper(vh->Close, 1, vh);
967 return 0;
968 }
969 uefi_call_wrapper(fh->Close, 1, fh);
970 uefi_call_wrapper(vh->Close, 1, vh);
971
972 return 1;
973}
974
20f6cde6
MG
975/*
976 * Generate the path of an executable given shim's path and the name
977 * of the executable
978 */
822d089e
GCPL
979static EFI_STATUS generate_path(EFI_LOADED_IMAGE *li, CHAR16 *ImagePath,
980 EFI_DEVICE_PATH **grubpath, CHAR16 **PathName)
f898777d 981{
0db1af8a 982 EFI_DEVICE_PATH *devpath;
f898777d 983 EFI_HANDLE device;
bc6aaefa 984 int i;
db54b0a4
MG
985 unsigned int pathlen = 0;
986 EFI_STATUS efi_status = EFI_SUCCESS;
bc6aaefa 987 CHAR16 *bootpath;
f898777d 988
f898777d 989 device = li->DeviceHandle;
0db1af8a 990 devpath = li->FilePath;
f898777d 991
bc6aaefa 992 bootpath = DevicePathToStr(devpath);
f898777d 993
bc6aaefa 994 pathlen = StrLen(bootpath);
f898777d 995
bc6aaefa
MG
996 for (i=pathlen; i>0; i--) {
997 if (bootpath[i] == '\\')
998 break;
f898777d
MG
999 }
1000
bc6aaefa
MG
1001 bootpath[i+1] = '\0';
1002
cbe21407 1003 if (i == 0 || bootpath[i-i] == '\\')
00ced0c1
MG
1004 bootpath[i] = '\0';
1005
822d089e 1006 *PathName = AllocatePool(StrSize(bootpath) + StrSize(ImagePath));
f898777d 1007
db54b0a4 1008 if (!*PathName) {
0db1af8a
MG
1009 Print(L"Failed to allocate path buffer\n");
1010 efi_status = EFI_OUT_OF_RESOURCES;
1011 goto error;
f898777d
MG
1012 }
1013
bc6aaefa 1014 *PathName[0] = '\0';
155a76bb
PJ
1015 if (StrnCaseCmp(bootpath, ImagePath, StrLen(bootpath)))
1016 StrCat(*PathName, bootpath);
822d089e 1017 StrCat(*PathName, ImagePath);
db54b0a4
MG
1018
1019 *grubpath = FileDevicePath(device, *PathName);
1020
1021error:
1022 return efi_status;
1023}
1024
1025/*
20f6cde6 1026 * Open the second stage bootloader and read it into a buffer
db54b0a4 1027 */
822d089e
GCPL
1028static EFI_STATUS load_image (EFI_LOADED_IMAGE *li, void **data,
1029 int *datasize, CHAR16 *PathName)
db54b0a4
MG
1030{
1031 EFI_GUID simple_file_system_protocol = SIMPLE_FILE_SYSTEM_PROTOCOL;
1032 EFI_GUID file_info_id = EFI_FILE_INFO_ID;
1033 EFI_STATUS efi_status;
1034 EFI_HANDLE device;
1035 EFI_FILE_INFO *fileinfo = NULL;
1036 EFI_FILE_IO_INTERFACE *drive;
1037 EFI_FILE *root, *grub;
6eb1eca4 1038 UINTN buffersize = sizeof(EFI_FILE_INFO);
db54b0a4
MG
1039
1040 device = li->DeviceHandle;
f898777d 1041
20f6cde6
MG
1042 /*
1043 * Open the device
1044 */
0db1af8a 1045 efi_status = uefi_call_wrapper(BS->HandleProtocol, 3, device,
ed711b02
MG
1046 &simple_file_system_protocol,
1047 (void **)&drive);
f898777d 1048
0db1af8a
MG
1049 if (efi_status != EFI_SUCCESS) {
1050 Print(L"Failed to find fs\n");
1051 goto error;
1052 }
f898777d 1053
0db1af8a
MG
1054 efi_status = uefi_call_wrapper(drive->OpenVolume, 2, drive, &root);
1055
1056 if (efi_status != EFI_SUCCESS) {
1057 Print(L"Failed to open fs\n");
1058 goto error;
1059 }
f898777d 1060
20f6cde6
MG
1061 /*
1062 * And then open the file
1063 */
f898777d
MG
1064 efi_status = uefi_call_wrapper(root->Open, 5, root, &grub, PathName,
1065 EFI_FILE_MODE_READ, 0);
1066
1067 if (efi_status != EFI_SUCCESS) {
1068 Print(L"Failed to open %s - %lx\n", PathName, efi_status);
0db1af8a
MG
1069 goto error;
1070 }
1071
1072 fileinfo = AllocatePool(buffersize);
1073
1074 if (!fileinfo) {
1075 Print(L"Unable to allocate file info buffer\n");
1076 efi_status = EFI_OUT_OF_RESOURCES;
1077 goto error;
f898777d
MG
1078 }
1079
20f6cde6
MG
1080 /*
1081 * Find out how big the file is in order to allocate the storage
1082 * buffer
1083 */
f898777d
MG
1084 efi_status = uefi_call_wrapper(grub->GetInfo, 4, grub, &file_info_id,
1085 &buffersize, fileinfo);
1086
1087 if (efi_status == EFI_BUFFER_TOO_SMALL) {
cbe21407 1088 FreePool(fileinfo);
f898777d
MG
1089 fileinfo = AllocatePool(buffersize);
1090 if (!fileinfo) {
0db1af8a
MG
1091 Print(L"Unable to allocate file info buffer\n");
1092 efi_status = EFI_OUT_OF_RESOURCES;
1093 goto error;
f898777d
MG
1094 }
1095 efi_status = uefi_call_wrapper(grub->GetInfo, 4, grub,
1096 &file_info_id, &buffersize,
1097 fileinfo);
1098 }
1099
1100 if (efi_status != EFI_SUCCESS) {
1101 Print(L"Unable to get file info\n");
0db1af8a 1102 goto error;
f898777d
MG
1103 }
1104
1105 buffersize = fileinfo->FileSize;
0db1af8a 1106
7db60bd8 1107 *data = AllocatePool(buffersize);
f898777d 1108
7db60bd8 1109 if (!*data) {
f898777d 1110 Print(L"Unable to allocate file buffer\n");
0db1af8a
MG
1111 efi_status = EFI_OUT_OF_RESOURCES;
1112 goto error;
f898777d 1113 }
20f6cde6
MG
1114
1115 /*
1116 * Perform the actual read
1117 */
f898777d 1118 efi_status = uefi_call_wrapper(grub->Read, 3, grub, &buffersize,
7db60bd8 1119 *data);
f898777d 1120
0db1af8a
MG
1121 if (efi_status == EFI_BUFFER_TOO_SMALL) {
1122 FreePool(*data);
1123 *data = AllocatePool(buffersize);
1124 efi_status = uefi_call_wrapper(grub->Read, 3, grub,
1125 &buffersize, *data);
f898777d
MG
1126 }
1127
1128 if (efi_status != EFI_SUCCESS) {
0db1af8a
MG
1129 Print(L"Unexpected return from initial read: %x, buffersize %x\n", efi_status, buffersize);
1130 goto error;
f898777d
MG
1131 }
1132
7db60bd8 1133 *datasize = buffersize;
f898777d 1134
cbe21407
MG
1135 FreePool(fileinfo);
1136
f898777d 1137 return EFI_SUCCESS;
0db1af8a
MG
1138error:
1139 if (*data) {
1140 FreePool(*data);
1141 *data = NULL;
1142 }
6f161626 1143
0db1af8a
MG
1144 if (fileinfo)
1145 FreePool(fileinfo);
1146 return efi_status;
f898777d
MG
1147}
1148
20f6cde6
MG
1149/*
1150 * Protocol entry point. If secure boot is enabled, verify that the provided
1151 * buffer is signed with a trusted key.
1152 */
db54b0a4 1153EFI_STATUS shim_verify (void *buffer, UINT32 size)
f4b24734
MG
1154{
1155 EFI_STATUS status;
1156 PE_COFF_LOADER_IMAGE_CONTEXT context;
1157
6279b58e
MG
1158 if (!secure_mode())
1159 return EFI_SUCCESS;
1160
ce78d2d2 1161 status = read_header(buffer, size, &context);
f4b24734
MG
1162
1163 if (status != EFI_SUCCESS)
1164 return status;
1165
0a6565c5 1166 status = verify_buffer(buffer, size, &context);
f4b24734
MG
1167
1168 return status;
1169}
1170
20f6cde6
MG
1171/*
1172 * Load and run an EFI executable
1173 */
cec6a0a9 1174EFI_STATUS start_image(EFI_HANDLE image_handle, CHAR16 *ImagePath)
822d089e 1175{
cec6a0a9 1176 EFI_GUID loaded_image_protocol = LOADED_IMAGE_PROTOCOL;
822d089e 1177 EFI_STATUS efi_status;
cec6a0a9 1178 EFI_LOADED_IMAGE *li, li_bak;
cec6a0a9 1179 EFI_DEVICE_PATH *path;
1c595706
MG
1180 CHAR16 *PathName = NULL;
1181 void *sourcebuffer = NULL;
1182 UINTN sourcesize = 0;
822d089e
GCPL
1183 void *data = NULL;
1184 int datasize;
1185
20f6cde6
MG
1186 /*
1187 * We need to refer to the loaded image protocol on the running
1188 * binary in order to find our path
1189 */
cec6a0a9 1190 efi_status = uefi_call_wrapper(BS->HandleProtocol, 3, image_handle,
ed711b02 1191 &loaded_image_protocol, (void **)&li);
cec6a0a9
GCPL
1192
1193 if (efi_status != EFI_SUCCESS) {
1194 Print(L"Unable to init protocol\n");
1195 return efi_status;
1196 }
1197
20f6cde6
MG
1198 /*
1199 * Build a new path from the existing one plus the executable name
1200 */
cec6a0a9
GCPL
1201 efi_status = generate_path(li, ImagePath, &path, &PathName);
1202
1203 if (efi_status != EFI_SUCCESS) {
1204 Print(L"Unable to generate path: %s\n", ImagePath);
1205 goto done;
1206 }
1207
1c595706
MG
1208 if (findNetboot(image_handle)) {
1209 efi_status = parseNetbootinfo(image_handle);
1210 if (efi_status != EFI_SUCCESS) {
1211 Print(L"Netboot parsing failed: %d\n", efi_status);
1212 return EFI_PROTOCOL_ERROR;
1213 }
1214 efi_status = FetchNetbootimage(image_handle, &sourcebuffer,
1215 &sourcesize);
1216 if (efi_status != EFI_SUCCESS) {
1217 Print(L"Unable to fetch TFTP image\n");
1218 return efi_status;
1219 }
1220 data = sourcebuffer;
1221 datasize = sourcesize;
1222 } else {
4ad234f1
MG
1223 /*
1224 * Read the new executable off disk
1225 */
1c595706 1226 efi_status = load_image(li, &data, &datasize, PathName);
822d089e 1227
1c595706
MG
1228 if (efi_status != EFI_SUCCESS) {
1229 Print(L"Failed to load image\n");
1230 goto done;
1231 }
822d089e
GCPL
1232 }
1233
20f6cde6
MG
1234 /*
1235 * We need to modify the loaded image protocol entry before running
1236 * the new binary, so back it up
1237 */
822d089e
GCPL
1238 CopyMem(&li_bak, li, sizeof(li_bak));
1239
20f6cde6
MG
1240 /*
1241 * Verify and, if appropriate, relocate and execute the executable
1242 */
822d089e
GCPL
1243 efi_status = handle_image(data, datasize, li);
1244
1245 if (efi_status != EFI_SUCCESS) {
1246 Print(L"Failed to load image\n");
1247 CopyMem(li, &li_bak, sizeof(li_bak));
1248 goto done;
1249 }
1250
20f6cde6
MG
1251 /*
1252 * The binary is trusted and relocated. Run it
1253 */
cbe21407 1254 efi_status = uefi_call_wrapper(entry_point, 2, image_handle, systab);
822d089e 1255
20f6cde6
MG
1256 /*
1257 * Restore our original loaded image values
1258 */
822d089e
GCPL
1259 CopyMem(li, &li_bak, sizeof(li_bak));
1260done:
cbe21407
MG
1261 if (PathName)
1262 FreePool(PathName);
1263
1264 if (data)
1265 FreePool(data);
1266
822d089e
GCPL
1267 return efi_status;
1268}
1269
20f6cde6
MG
1270/*
1271 * Load and run grub. If that fails because grub isn't trusted, load and
1272 * run MokManager.
1273 */
db54b0a4 1274EFI_STATUS init_grub(EFI_HANDLE image_handle)
b2fe1780
MG
1275{
1276 EFI_STATUS efi_status;
f4b24734 1277
6d6b0221
PJ
1278 if (should_use_fallback(image_handle))
1279 efi_status = start_image(image_handle, FALLBACK);
1280 else
1281 efi_status = start_image(image_handle, second_stage);
b2fe1780 1282
ef8c9962
MG
1283 if (efi_status != EFI_SUCCESS)
1284 efi_status = start_image(image_handle, MOK_MANAGER);
db54b0a4
MG
1285
1286 return efi_status;
1287}
1288
20f6cde6
MG
1289/*
1290 * Copy the boot-services only MokList variable to the runtime-accessible
1291 * MokListRT variable. It's not marked NV, so the OS can't modify it.
1292 */
a903fb10
GCPL
1293EFI_STATUS mirror_mok_list()
1294{
1295 EFI_GUID shim_lock_guid = SHIM_LOCK_GUID;
1296 EFI_STATUS efi_status;
1297 UINT32 attributes;
1298 void *Data = NULL;
1299 UINTN DataSize = 0;
1300
1301 efi_status = get_variable(L"MokList", shim_lock_guid, &attributes,
1302 &DataSize, &Data);
1303
1304 if (efi_status != EFI_SUCCESS) {
1305 goto done;
1306 }
1307
1308 efi_status = uefi_call_wrapper(RT->SetVariable, 5, L"MokListRT",
1309 &shim_lock_guid,
1310 EFI_VARIABLE_BOOTSERVICE_ACCESS
1311 | EFI_VARIABLE_RUNTIME_ACCESS,
1312 DataSize, Data);
1313 if (efi_status != EFI_SUCCESS) {
1314 Print(L"Failed to set MokListRT %d\n", efi_status);
1315 }
1316
1317done:
1318 return efi_status;
1319}
1320
20f6cde6
MG
1321/*
1322 * Check if a variable exists
1323 */
d5a2d9ea 1324static BOOLEAN check_var(CHAR16 *varname)
4b34567d
GCPL
1325{
1326 EFI_STATUS efi_status;
e470969e 1327 EFI_GUID shim_lock_guid = SHIM_LOCK_GUID;
1041805a 1328 UINTN size = sizeof(UINT32);
801d1b93 1329 UINT32 MokVar;
e470969e
GCPL
1330 UINT32 attributes;
1331
d5a2d9ea 1332 efi_status = uefi_call_wrapper(RT->GetVariable, 5, varname,
1041805a 1333 &shim_lock_guid, &attributes,
d5a2d9ea 1334 &size, (void *)&MokVar);
e470969e 1335
d5a2d9ea
MG
1336 if (efi_status == EFI_SUCCESS || efi_status == EFI_BUFFER_TOO_SMALL)
1337 return TRUE;
4b34567d 1338
d5a2d9ea
MG
1339 return FALSE;
1340}
4b34567d 1341
20f6cde6
MG
1342/*
1343 * If the OS has set any of these variables we need to drop into MOK and
1344 * handle them appropriately
1345 */
d5a2d9ea
MG
1346EFI_STATUS check_mok_request(EFI_HANDLE image_handle)
1347{
1348 EFI_STATUS efi_status;
4b34567d 1349
d5a2d9ea 1350 if (check_var(L"MokNew") || check_var(L"MokSB") ||
92a136d8
GCPL
1351 check_var(L"MokPW") || check_var(L"MokAuth") ||
1352 check_var(L"MokDel")) {
9272bc5b 1353 efi_status = start_image(image_handle, MOK_MANAGER);
4b34567d 1354
9272bc5b
MG
1355 if (efi_status != EFI_SUCCESS) {
1356 Print(L"Failed to start MokManager\n");
1357 return efi_status;
1358 }
4b34567d 1359 }
4b34567d 1360
9272bc5b 1361 return EFI_SUCCESS;
4b34567d
GCPL
1362}
1363
20f6cde6
MG
1364/*
1365 * Verify that MokSBState is valid, and if appropriate set insecure mode
1366 */
1367
9eaadb0d
MG
1368static EFI_STATUS check_mok_sb (void)
1369{
1370 EFI_GUID shim_lock_guid = SHIM_LOCK_GUID;
1371 EFI_STATUS status = EFI_SUCCESS;
1372 void *MokSBState = NULL;
1373 UINTN MokSBStateSize = 0;
1374 UINT32 attributes;
1375
1376 status = get_variable(L"MokSBState", shim_lock_guid, &attributes,
1377 &MokSBStateSize, &MokSBState);
1378
1379 if (status != EFI_SUCCESS)
1380 return EFI_ACCESS_DENIED;
1381
20f6cde6
MG
1382 /*
1383 * Delete and ignore the variable if it's been set from or could be
1384 * modified by the OS
1385 */
9eaadb0d
MG
1386 if (attributes & EFI_VARIABLE_RUNTIME_ACCESS) {
1387 Print(L"MokSBState is compromised! Clearing it\n");
1388 if (LibDeleteVariable(L"MokSBState", &shim_lock_guid) != EFI_SUCCESS) {
1389 Print(L"Failed to erase MokSBState\n");
1390 }
1391 status = EFI_ACCESS_DENIED;
1392 } else {
1393 if (*(UINT8 *)MokSBState == 1) {
1394 insecure_mode = 1;
1395 }
1396 }
1397
1398 return status;
4b34567d
GCPL
1399}
1400
09e2c939
GCPL
1401/*
1402 * Check the load options to specify the second stage loader
1403 */
1404EFI_STATUS set_second_stage (EFI_HANDLE image_handle)
1405{
1406 EFI_STATUS status;
1407 EFI_LOADED_IMAGE *li;
1408 CHAR16 *start = NULL, *c;
1409 int i, remaining_size = 0;
0283024e
GCPL
1410 CHAR16 *loader_str = NULL;
1411 int loader_len = 0;
09e2c939
GCPL
1412
1413 second_stage = DEFAULT_LOADER;
1414 load_options = NULL;
1415 load_options_size = 0;
1416
1417 status = uefi_call_wrapper(BS->HandleProtocol, 3, image_handle,
1418 &LoadedImageProtocol, (void **) &li);
1419 if (status != EFI_SUCCESS) {
1420 Print (L"Failed to get load options\n");
1421 return status;
1422 }
1423
1424 /* Expect a CHAR16 string with at least one CHAR16 */
1425 if (li->LoadOptionsSize < 4 || li->LoadOptionsSize % 2 != 0) {
1426 return EFI_BAD_BUFFER_SIZE;
1427 }
1428 c = (CHAR16 *)(li->LoadOptions + (li->LoadOptionsSize - 2));
1429 if (*c != L'\0') {
1430 return EFI_BAD_BUFFER_SIZE;
1431 }
1432
0283024e
GCPL
1433 /*
1434 * UEFI shell copies the whole line of the command into LoadOptions.
1435 * We ignore the string before the first L' ', i.e. the name of this
1436 * program.
1437 */
09e2c939
GCPL
1438 for (i = 0; i < li->LoadOptionsSize; i += 2) {
1439 c = (CHAR16 *)(li->LoadOptions + i);
1440 if (*c == L' ') {
1441 *c = L'\0';
1442 start = c + 1;
1443 remaining_size = li->LoadOptionsSize - i - 2;
1444 break;
1445 }
1446 }
1447
0283024e
GCPL
1448 if (!start || remaining_size <= 0)
1449 return EFI_SUCCESS;
6e1bd3dc 1450
0283024e
GCPL
1451 for (i = 0; start[i] != '\0'; i++) {
1452 if (start[i] == L' ' || start[i] == L'\0')
1453 break;
1454 loader_len++;
1455 }
1456
1457 /*
1458 * Setup the name of the alternative loader and the LoadOptions for
1459 * the loader
1460 */
1461 if (loader_len > 0) {
1462 loader_str = AllocatePool((loader_len + 1) * sizeof(CHAR16));
1463 if (!loader_str) {
1464 Print(L"Failed to allocate loader string\n");
1465 return EFI_OUT_OF_RESOURCES;
1466 }
1467 for (i = 0; i < loader_len; i++)
1468 loader_str[i] = start[i];
1469 loader_str[loader_len] = L'\0';
1470
1471 second_stage = loader_str;
09e2c939
GCPL
1472 load_options = start;
1473 load_options_size = remaining_size;
1474 }
1475
1476 return EFI_SUCCESS;
1477}
1478
db54b0a4
MG
1479EFI_STATUS efi_main (EFI_HANDLE image_handle, EFI_SYSTEM_TABLE *passed_systab)
1480{
1481 EFI_GUID shim_lock_guid = SHIM_LOCK_GUID;
1482 static SHIM_LOCK shim_lock_interface;
1483 EFI_HANDLE handle = NULL;
0a232ca9 1484 EFI_STATUS efi_status;
e75294e5
PJ
1485 UINT8 verbose_check;
1486 UINTN verbose_check_size;
1487 UINT32 attributes;
1488 EFI_GUID global_var = EFI_GLOBAL_VARIABLE;
db54b0a4 1489
20f6cde6
MG
1490 /*
1491 * Set up the shim lock protocol so that grub and MokManager can
1492 * call back in and use shim functions
1493 */
db54b0a4 1494 shim_lock_interface.Verify = shim_verify;
0a6565c5
MG
1495 shim_lock_interface.Hash = generate_hash;
1496 shim_lock_interface.Context = read_header;
db54b0a4
MG
1497
1498 systab = passed_systab;
1499
20f6cde6
MG
1500 /*
1501 * Ensure that gnu-efi functions are available
1502 */
db54b0a4
MG
1503 InitializeLib(image_handle, systab);
1504
e75294e5
PJ
1505 verbose_check_size = 1;
1506 efi_status = get_variable(L"SHIM_VERBOSE", global_var, &attributes,
1507 &verbose_check_size, (void *)&verbose_check);
1508 if (!EFI_ERROR(efi_status))
1509 verbose = verbose_check;
1510
09e2c939
GCPL
1511 /* Set the second stage loader */
1512 set_second_stage (image_handle);
1513
20f6cde6
MG
1514 /*
1515 * Check whether the user has configured the system to run in
1516 * insecure mode
1517 */
9eaadb0d
MG
1518 check_mok_sb();
1519
20f6cde6
MG
1520 /*
1521 * Tell the user that we're in insecure mode if necessary
1522 */
9eaadb0d
MG
1523 if (insecure_mode) {
1524 Print(L"Booting in insecure mode\n");
1525 uefi_call_wrapper(BS->Stall, 1, 2000000);
1526 }
1527
20f6cde6
MG
1528 /*
1529 * Install the protocol
1530 */
1531 uefi_call_wrapper(BS->InstallProtocolInterface, 4, &handle,
1532 &shim_lock_guid, EFI_NATIVE_INTERFACE,
1533 &shim_lock_interface);
1534
1535 /*
1536 * Enter MokManager if necessary
1537 */
4b34567d
GCPL
1538 efi_status = check_mok_request(image_handle);
1539
20f6cde6
MG
1540 /*
1541 * Copy the MOK list to a runtime variable so the kernel can make
1542 * use of it
1543 */
a903fb10
GCPL
1544 efi_status = mirror_mok_list();
1545
20f6cde6
MG
1546 /*
1547 * Hand over control to the second stage bootloader
1548 */
db54b0a4 1549
0a232ca9
MG
1550 efi_status = init_grub(image_handle);
1551
20f6cde6
MG
1552 /*
1553 * If we're back here then clean everything up before exiting
1554 */
0a232ca9
MG
1555 uefi_call_wrapper(BS->UninstallProtocolInterface, 3, handle,
1556 &shim_lock_guid, &shim_lock_interface);
1557
0283024e
GCPL
1558 /*
1559 * Free the space allocated for the alternative 2nd stage loader
1560 */
1561 if (load_options_size > 0)
1562 FreePool(second_stage);
1563
0a232ca9 1564 return efi_status;
b2fe1780 1565}