Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

pcks#7(.p7a) format signature authenticate issue #12

Open
leitao1019 opened this issue Jul 31, 2024 · 4 comments
Open

pcks#7(.p7a) format signature authenticate issue #12

leitao1019 opened this issue Jul 31, 2024 · 4 comments

Comments

@leitao1019
Copy link

leitao1019 commented Jul 31, 2024

Dear Developer,

I am trying to use SEloader to authenticate the non-PE files in the UEFI secure boot process, but found that SEloader only authenticate the signature file (*.p7a) but not verify the original file.
I'd like to verify the zipped kernel file bzImage via pkcs#7(p7a) signatures, I generated a signature file bzImage.p7a for it. But when I replace a new kernel file and keep using the previous signature file(bzImage.p7a). SEloader also authenticate successfully.
seems SELoader did not verify the original file with .p7a format signature.

signing command:
selsign --key MOK.key --cert MOK.der --content-attached bzImage

logs:

lib/efi/mok2verify.c:133: attempting to verify the file /imgy/bzImage ...
Attempting to verify file \imgy\bzImage by MOK2 Verify Protocol ...
Signature verification is required
Attempting to load the content-attached signature file \imgy\bzImage.p7a ...
File \imgy\bzImage.p7a loaded (1498-byte)
Signed content extracted (73-byte): 53454C53011900000010000000010000002000000000000000090000000000000000000000200000009AB35409D6624926EB0F0F4D8A2AB4CA75B7FF2F03458374D1318350C09E04F1
Succeeded to verify PKCS#7 attached signature (signed content 73-byte)
Signature format revision 1 supported
Content attached in SELoader signature
Succeeded to verify the attached signature
The file \imgy\bzImage loaded with the exit code 0x0
Succeeded to verify file \imgy\bzImage by MOK2 Verify Protocol
lib/efi/mok2verify.c:177: succeeded to verify file /imgy/bzImage

@gdmeunier
Copy link

Hello,
even if it's a long while ago let's try to understand why it doesn't verify your bzImage file:

Succeeded to verify file \imgy\bzImage by MOK2 Verify Protocol

Look at the line above, SELoader here actually didn't verify the file itself; it asked your UEFI Secure Boot implementation to do the MOK2 verify on it.

The MOK2 Verify Protocol is standard and part of UEFI itself.

So SELoader first did what your firmware cannot do itself, verifying whether you want to also validate the signatures of non-PE files during boot.
Then it asked your firmware to verify the integrity of this non-PE file after having successfully determined that your signature file (p7a) contains a whitelisted certificate inside.

If you just ask the MOK2 Verify Protocol to verify files with any certificate (no whitelist verification), then I can just put a fake bzImage file with a correct p7a file for it using my own fake certificate.
It won't be your cert and yet it will work because the MOK2 Verify call doesn't care about the trust status of the certificate, only whether the file was correctly signed by that cert...

I generated a signature file bzImage.p7a for it. But when I replace a new kernel file and keep using the previous signature file(bzImage.p7a)

And then you say that SELoader still correctly validated your bzImage even if you replaced it later with a different (modified) one?

Can you try running a third-party PKCS#7 signature verification utility on the modified bzImage file to make sure that other tools say that it's an invalid signature?

Succeeded to verify PKCS#7 attached signature (signed content 73-byte)
Signature format revision 1 supported
Content attached in SELoader signature
Succeeded to verify the attached signature
The file \imgy\bzImage loaded with the exit code 0x0
Succeeded to verify file \imgy\bzImage by MOK2 Verify Protocol

Here you will see that SELoader manually handled the verification of your PKCS#7 file (.p7a) and it was a correct whitelisted certificate inside.
Then it successfully verified that your certificate (whitelisted one) indeed signed this PKCS#7 signature for bzImage.

But the only thing SELoader didn't do itself was verifying the bzImage file itself, which it instead asked your firmware to do on its behalf (using MOK2 Verify unlike your .p7a file).

So, the things you should do are:

  • Try verifying your replaced bzImage with the .p7a signature in a third-party program (on Linux/Windows/Mac OS) and verify that it fails to verify on it
  • Try using the same SELoader configuration & files on a computer from a different manufacturer (and therefore different UEFI implementations)

It it still works then it's an error in SELoader which wouldn't correctly handle rare MOK2 failure scenarios, but if it fails on a different computer then your manufacturer's UEFI implementation for MOK2 Verify is faulty and you will need to replace it (by using a third-party DXE driver & replacing it in your firmware with UEFITool 0.27)

@gdmeunier
Copy link

I can also suggest you to modify some code in SELoader then recompile it for better debugging:

Src/Efi/Lib/Mok2Verify.c:

STATIC EFI_STATUS EFIAPI
Mok2VerifyFile(IN EFI_MOK2_VERIFY_PROTOCOL *This, IN CONST CHAR16 *Path)
{
	if (!This || !Path)
		return EFI_INVALID_PARAMETER;

	EfiConsoleTraceDebug(L"Attempting to verify file %s by MOK2 Verify "
			     L"Protocol ...\n", Path);

	VOID *Data = NULL;
	UINTN DataSize = 0;
	EFI_STATUS Status;

	Status = EfiFileLoad(Path, &Data, &DataSize);
	if (!EFI_ERROR(Status))
		EfiConsoleTraceDebug(L"Succeeded to verify file %s by MOK2 "
				     L"Verify Protocol\n", Path);
	else
		EfiConsoleTraceDebug(L"Failed to verify file %s by MOK2 "
				     L"Verify Protocol\n", Path);

	return Status;
}

This is the function that gets called to verify your bzImage file, it simply tries to do a FileLoad then the MOK2 Verify hook handles the verification.
But an interesting thing is that it prints messages in boot logs using EfiConsoleTraceDebug() for both failure & success scenarios.

But now look at this function:

EFI_STATUS
Mok2VerifyInitialize(VOID)
{
	EFI_STATUS Status;

	Status = EfiProtocolInstall(&Mok2VerifyHandle,
				    &gEfiMok2VerifyProtocolGuid,
				    (VOID *)&Mok2VerifyProtocol);
        if (EFI_ERROR(Status)) {
		EfiConsolePrintError(L"Failed to install MOK2 Verify "
				     L"Protocol (err: 0x%x)\n", Status);
		return Status;
        }

	EfiConsoleTraceDebug(L"MOK2 Verify Protocol installed\n");

        return EFI_SUCCESS;
}

That function however uses EfiConsolePrintError() to display error in the logs when verification fails, and EfiConsoleTraceDebug() only gets called when the MOK2 Verify Protocol installation is successful.

So if your UEFI firmware had a bug in installing the MOK2 Verify protocol and didn't support displaying EfiConsolePrintError() output during boot, then you would never be informed that the MOK2 Verify protocol couldn't be installed.

I also don't see in your logs the line MOK2 Verify Protocol installed, do you have the full (non-trimmed) logs?

And since SELoader works by using MOK2 Protocol hooks instead of direct verification of files, if the MOK2 protocol cannot be installed then all calls to EfiFileLoad() with an averagely correct file will succeed (because there will be no hook available to intercept its loading for verification).

So more things you can do are to change the EfiConsolePrintError() calls to EfiConsoleTraceDebug() even if they're not for errors, incase your UEFI firmware doesn't correctly display error output (basically stderr on common operating systems).

Then retry the same SELoader boot scenario and compare your logs to make sure that all the needed protocols & hooks were sucessfully installed, and yet SELoader somehow accepted to load your bzImage file.

@leitao1019
Copy link
Author

Hi @gdmeunier ,
I appreciate your effort in your kind response and detailed analysis.

I tried to verify it again with the grub.cfg file, grub.cfg.p7a is the signature file of grub.cfg.

  1. I generated the signature of grub.cfg with the cert and key with the below command:
BOOT/EFI/axos# selsign --key $vend_key --cert $vend_crt --content-attached grub.cfg
root@ASM5001:/BOOT/EFI/axos# openssl smime -verify -in grub.cfg.p7a -inform DER -noverify -CAfile ./vendor_cert.crt -out grub.verify
Verification successful
root@ASM5001:/BOOT/EFI/axos# sha256sum grub.cfg
3138a6aca90af1d91b69763cd47febb9a58889574b5e97eeaaeda886836be95d  grub.cfg
root@ASM5001:/BOOT/EFI/axos# sha256sum grub.cfg.p7a 
b5303cb565b9a0afe223faf2d967b26fe7308b3ffdb7dc28668f451d5c2f15d7  grub.cfg.p7a
  1. reboot the system and confirm that the system can boot up with secure boot enabled.
  2. change the content of grub.cfg, but keep grub.cfg.p7a NO change. as you can see the sha256sum of new grub.cfg differs from above, but the grub.cfg.p7a is the same.
root@ASM5001:/BOOT/EFI/axos# sha256sum grub.cfg
e66b4e8683e791be2c5b06e34eba4f9c982cadd6c21d3ab0ac27df66d3b64609  grub.cfg
root@ASM5001:/BOOT/EFI/axos# sha256sum grub.cfg.p7a 
b5303cb565b9a0afe223faf2d967b26fe7308b3ffdb7dc28668f451d5c2f15d7  grub.cfg.p7a
  1. reboot the system again, and check the boot status. The system could boot up with secure boot successfully.

I attached the full boot log for your reference. please help to check.
according to the log, seems the MOK2 protocol has been installed successfully in the firmware.

thanks in advance~

shim-bootup.log

@gdmeunier
Copy link

Hello,

The compressed version of your log is as below (without the other log messages):

Version 2.22.1286. Copyright (C) 2024 AMI
Kontron Version BID7R906. (C) 2020 Kontron Europe GmbH.
Press <DEL> or <ESC> to enter setup.shim.c:1890:efi_main() vendor_authorized:0x5ED0E010 vendor_authorized_size:785

shim.c:1705:shim_init() UEFI SHIM
$Version: 15.8 $
$BuildMachine: buildhost $
$Commit: 5914984a1ffeab841f482c791426d7ca9935a5e6 $

include/hexdump.h:92:vhexdumpf() hexdump of a NULL pointer!
shim.c:886:load_image() attempting to load \EFI\axos\SELoaderx64.efi

shim.c:611:verify_buffer_authenticode() check_allowlist: Not Found
shim.c:673:verify_buffer_authenticode() Attempting to verify signature 0:
shim.c:154:check_db_cert_in_ram() trying to verify cert 0 (db)
shim.c:164:check_db_cert_in_ram() AuthenticodeVerify() succeeded: 1

pe.c:378:verify_sbat_section() seloader, 1, SELoader, seloader, 0.4.6, https://github.com/jiazhang0/SELoader/

Verification succeeded

SELoader 0.4.6+git8b90f76a8df51d9020e67824026556434f407086 launched
Platform firmware is in User mode
Platform firmware is operating in Secure Boot mode
MOK Verify Protocol is installed
Assuming MOK Secure Boot enabled
Shim loader is operating in MOK Secure Boot mode
Succeeded to hook EFI Security2 Architectural Protocol
Succeeded to hook MOK Verify Protocol
Attempting to initialize MOK2 Verify Protocol ...
MOK2 Verify Protocol installed
UEFI Secure Boot Mode: Enabled
Setup Mode: No
MOK Verify Protocol installed: Yes
MOK Secure Boot Mode: Enabled
Preparing to load grubx64.efi ...
Preparing to start the image grubx64.efi ...
Succeeded to hook EFI Security2 Architectural Protocol

So from your log I guess that you have a 2024 up-to-date BIOS by AMI.
I also see that you use Shim version 15.8 which is too recent for your SELoader build.

This line says that you have an up-to-date BIOS:
Version 2.22.1286. Copyright (C) 2024 AMI

These ones give your Shim version number:

shim.c:1705:shim_init() UEFI SHIM
$Version: 15.8 $

Your SELoader build is 0.4.6 from 2018 (commit 8b90f76)

  • This SELoader version only supports Shim versions 14.x or earlier

It's this line that tells which exact version of SELoader you have:
SELoader 0.4.6+git8b90f76a8df51d9020e67824026556434f407086 launched

An update was released in 2022 (commit 7df5b30):

  • This update specifically fixes a Shim version 15.x problem with MokListRT variables not being found, and PKCS#7 verifications being skipped instead of rejecting the files

In the commits list you can see the differences between the 2018 & 2022 version of SELoader:

You need to pull the latest revision of SELoader named Fix compatibility with shim 15.4 (ubuntu shim-signed 1.40.7+15.4-0ubuntu9) or apply the changes manually to your existing SELoader code.

So you just have to rebuild SELoader from the latest commit and retry booting the files, but afterwards make sure to keep using Shim 15.x versions only:

  • In semantic versioning, the first number is for the major version; so if one day you use Shim 16.x when it comes out, then this will be a major update (compatibility breaking)

The Secure Boot Setup Mode is correctly exited in your firmware, but that's something to remember when you will configure other computers for SELoader:

  • Setup Mode: No

Basically exiting Setup Mode means removing the manufacturer's Platform Key and using your own, but also generating your own 'DB' & 'DBX' and enrolling them in your firmware (adding atleast one file hash or cert inside 'DB').

If there's still any problem with SELoader then downgrade Shim to 15.4 since it's the exact version that was tested to work with the latest SELoader from 2022 (latest commit).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants