mirror of
https://github.com/jiazhang0/meta-secure-core.git
synced 2026-01-12 01:00:15 +00:00
meta-secure-core: initial commit
Signed-off-by: Lans Zhang <jia.zhang@windriver.com>
This commit is contained in:
17
COPYING.MIT
Normal file
17
COPYING.MIT
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
in the Software without restriction, including without limitation the rights
|
||||||
|
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
copies of the Software, and to permit persons to whom the Software is
|
||||||
|
furnished to do so, subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in
|
||||||
|
all copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
|
THE SOFTWARE.
|
||||||
1
MAINTAINERS
Normal file
1
MAINTAINERS
Normal file
@@ -0,0 +1 @@
|
|||||||
|
Jia Zhang <lans.zhang2008@gmail.com>
|
||||||
60
README
Normal file
60
README
Normal file
@@ -0,0 +1,60 @@
|
|||||||
|
This README file contains information on the contents of the
|
||||||
|
meta-secure-core layer.
|
||||||
|
|
||||||
|
Please see the corresponding sections below for details.
|
||||||
|
|
||||||
|
|
||||||
|
Dependencies
|
||||||
|
============
|
||||||
|
|
||||||
|
This layer depends on:
|
||||||
|
|
||||||
|
URI: git://git.openembedded.org/bitbake
|
||||||
|
branch: master
|
||||||
|
|
||||||
|
URI: git://git.openembedded.org/openembedded-core
|
||||||
|
layers: meta
|
||||||
|
branch: master
|
||||||
|
|
||||||
|
|
||||||
|
Patches
|
||||||
|
=======
|
||||||
|
|
||||||
|
Please submit any patches against the meta-secure-core layer to the
|
||||||
|
maintainer:
|
||||||
|
|
||||||
|
Maintainer: Jia Zhang <lans.zhang2008@gmail.com>
|
||||||
|
|
||||||
|
|
||||||
|
Table of Contents
|
||||||
|
=================
|
||||||
|
|
||||||
|
I. Adding the meta-secure-core layer to your build
|
||||||
|
II. Misc
|
||||||
|
|
||||||
|
|
||||||
|
I. Adding the meta-secure-core layer to your build
|
||||||
|
=================================================
|
||||||
|
|
||||||
|
--- replace with specific instructions for the meta-secure-core layer ---
|
||||||
|
|
||||||
|
In order to use this layer, you need to make the build system aware of
|
||||||
|
it.
|
||||||
|
|
||||||
|
Assuming the meta-secure-core layer exists at the top-level of your
|
||||||
|
yocto build tree, you can add it to the build system by adding the
|
||||||
|
location of the meta-secure-core layer to bblayers.conf, along with any
|
||||||
|
other layers needed. e.g.:
|
||||||
|
|
||||||
|
BBLAYERS ?= " \
|
||||||
|
/path/to/yocto/meta \
|
||||||
|
/path/to/yocto/meta-poky \
|
||||||
|
/path/to/yocto/meta-yocto-bsp \
|
||||||
|
/path/to/yocto/meta-meta-secure-core \
|
||||||
|
"
|
||||||
|
|
||||||
|
|
||||||
|
II. Misc
|
||||||
|
========
|
||||||
|
|
||||||
|
--- replace with specific information about the meta-secure-core layer ---
|
||||||
95
README.md
Normal file
95
README.md
Normal file
@@ -0,0 +1,95 @@
|
|||||||
|
### meta-secure-env
|
||||||
|
This layer provides the following common and platform-specific security
|
||||||
|
features:
|
||||||
|
|
||||||
|
#### UEFI Secure Boot
|
||||||
|
For x86 platform, UEFI secure boot is the industry standard defined in the
|
||||||
|
UEFI spec, allowing images loaded by UEFI BIOS to be verified with the trusted
|
||||||
|
key. Whenever this feature is enabled, the bootloader and kernel will be
|
||||||
|
signed automatically during the build, implying the signed binaries are
|
||||||
|
contained by the resulting RPM and rootfs image.
|
||||||
|
|
||||||
|
Refer to [meta-efi-secure-boot](https://github.com/jiazhang0/meta-efi-secure-boot/blob/master/README.md) for more details.
|
||||||
|
|
||||||
|
#### MOK Secure Boot
|
||||||
|
For x86 platform, MOK secure boot is based on the UEFI secure boot, adding
|
||||||
|
the shim loader to chainloader the second-stage bootloader. Meanwhile,
|
||||||
|
the shim will also install a protocol which permits the second-stage bootloader
|
||||||
|
to perform similar binary validation, e.g, for linux kernel.
|
||||||
|
|
||||||
|
Refer to [meta-efi-secure-boot](https://github.com/jiazhang0/meta-efi-secure-boot/blob/master/README.md) for more details.
|
||||||
|
|
||||||
|
#### User key store
|
||||||
|
By default, the signing key used by UEFI/MOK secure boot is the sample key for
|
||||||
|
the purposes of development and demonstration. It is not recommended that
|
||||||
|
this sample key be used for a production device and should be replaced by
|
||||||
|
a secret key owned by the user.
|
||||||
|
|
||||||
|
Refer to [meta-signing-key](https://github.com/jiazhang0/meta-signing-key/blob/master/README.md)
|
||||||
|
for more details about how to construct an user key store.
|
||||||
|
|
||||||
|
#### TPM 1.x
|
||||||
|
This feature enables Trusted Platform Module 1.x support, including
|
||||||
|
kernel option changes to enable tpm drivers, and picking up TPM 1.x packages.
|
||||||
|
|
||||||
|
Refer to [meta-tpm](https://github.com/jiazhang0/meta-tpm/blob/master/README.md)
|
||||||
|
for more details.
|
||||||
|
|
||||||
|
#### TPM 2.0
|
||||||
|
This feature enables Trusted Platform Module 2.0 support, including
|
||||||
|
kernel option changes to enable tpm drivers, and picking up TPM 2.0 packages.
|
||||||
|
|
||||||
|
Trusted Platform Module (TPM 2.0) is a microcontroller that stores keys,
|
||||||
|
passwords, and digital certificates. A discrete TPM 2.0 offers the
|
||||||
|
capabilities as part of the overall platform security requirements.
|
||||||
|
|
||||||
|
Refer to [meta-tpm2](https://github.com/jiazhang0/meta-tpm2/blob/master/README.md)
|
||||||
|
for more details.
|
||||||
|
|
||||||
|
#### Encrypted storage
|
||||||
|
This feature gives 2 types of granularity for storage encryption. Data volume
|
||||||
|
encryption allows the user to create encryption partition with a passphrase
|
||||||
|
typed by the end user. Root filesystem encryption enables the data encryption on
|
||||||
|
the entire rootfs except the boot partition.
|
||||||
|
|
||||||
|
Both types of storage encryption are based on device-mapper crypt target,
|
||||||
|
which provides transparent encryption of block devices using the kernel crypto
|
||||||
|
API. Additionally, the utility cryptsetup is used to conveniently setup disk
|
||||||
|
encryption based on device-mapper crypt target.
|
||||||
|
|
||||||
|
Refer to [meta-encrypted-storage](https://github.com/jiazhang0/meta-encrypted-storage/blob/master/README.md) for more details.
|
||||||
|
|
||||||
|
#### Integrity
|
||||||
|
The Linux IMA subsystem introduces hooks within the Linux kernel to support
|
||||||
|
measuring the integrity of files that are loaded (including application code)
|
||||||
|
before it is executed or mmap()ed to memory. The measured value (hash) is then
|
||||||
|
registered in a log that can be consulted by administrators.
|
||||||
|
|
||||||
|
To support proven integrity of the files, the IMA subsystem can interact with
|
||||||
|
the TPM chip within the system to protect the registered hashes from tampering
|
||||||
|
by a rogue administrator or application. The IMA subsystem, as already
|
||||||
|
supported by the Linux kernel, supports reporting on the hashes of files and
|
||||||
|
commands ran by privileged accounts (and more if you create your own
|
||||||
|
measurement policies).
|
||||||
|
|
||||||
|
In addition, IMA appraisal can even register the measured value as an extended
|
||||||
|
attribute, and after subsequent measurement(s) validate this extended attribute
|
||||||
|
against the measured value and refuse to load the file (or execute the
|
||||||
|
application) if the hash does not match. In that case, the IMA subsystem allows
|
||||||
|
files and applications to be loaded if the hashes match (and will save the
|
||||||
|
updated hash if the file is modified) but refuse to load it if it doesn't. This
|
||||||
|
provides some protection against offline tampering of the files.
|
||||||
|
|
||||||
|
Refer to [meta-integrity](https://github.com/jiazhang0/meta-efi-secure-boot/blob/master/README.md)
|
||||||
|
for more details.
|
||||||
|
|
||||||
|
#### RPM signing
|
||||||
|
This feature provides the integrity verification for the RPM5 package.
|
||||||
|
|
||||||
|
Refer to [meta-rpm-signing](https://github.com/jiazhang0/meta-rpm-signing/blob/master/README.md)
|
||||||
|
for more details.
|
||||||
|
|
||||||
|
|
||||||
|
### Building the meta-secure-env layer
|
||||||
|
This layer should be added to the bblayers.conf file. To enable certain
|
||||||
|
feature provided by this layer, add the feature to the local.conf file.
|
||||||
463
meta-efi-secure-boot/README.md
Normal file
463
meta-efi-secure-boot/README.md
Normal file
@@ -0,0 +1,463 @@
|
|||||||
|
### EFI secure boot feature
|
||||||
|
This feature consists of two widely used secure boot technologies: UEFI Secure
|
||||||
|
Boot and MOK Secure Boot.
|
||||||
|
|
||||||
|
- UEFI Secure Boot is the industry standard defined in the UEFI spec, allowing the
|
||||||
|
images loaded by UEFI BIOS to be verified with the certificates corresponding to
|
||||||
|
the trusted keys.
|
||||||
|
- MOK (Machine Owner Key) Secure Boot is based on UEFI Secure Boot, adding
|
||||||
|
the shim bootloader to chainloader the next stage bootloader with the integrity
|
||||||
|
check using the shim-managed certificates corresponding to another set of
|
||||||
|
trusted keys which may be different than the trusted keys used by UEFI Secure
|
||||||
|
Boot.
|
||||||
|
|
||||||
|
In addition, this feature introduces the SELoader as the second-stage bootloader
|
||||||
|
and eventually chainliader to the third-stage bootloader "grub". With the
|
||||||
|
extension provided by SELoader, grub configuration files, kernel (even without
|
||||||
|
EFI stub support) and initrd can be authenticated. This capability is not
|
||||||
|
available in the shim bootloader.
|
||||||
|
|
||||||
|
Grub bootloader is enhanced to support lockdown mode. In this mode, the
|
||||||
|
edit, rescue and command line are protected in order to prevent from
|
||||||
|
tampering the kernel commandline or loading an unsigned boot component. Hence,
|
||||||
|
this lockdown protection can effectively defeat the attempts to disable the
|
||||||
|
kernel security mechanisms. The flexibility is also provided if the user
|
||||||
|
authentication is enabled. The user authenticated by a password check can enter
|
||||||
|
into edit and command line.
|
||||||
|
|
||||||
|
Therefore, using UEFI Secure Boot, SELoader, and grub lockdown together, the
|
||||||
|
boot process is completely trustworthy.
|
||||||
|
|
||||||
|
A complete boot flow with this feature is:
|
||||||
|
|
||||||
|
- UEFI BIOS boot manager (UEFI Secure Boot enabled) ->
|
||||||
|
- shim (verified by a DB certificate) ->
|
||||||
|
- SELoader (verified by a shim-managed certificate) ->
|
||||||
|
- grub (verified by a shim-managed certificate) ->
|
||||||
|
- grub.cfg (verified by a shim-managed certificate)
|
||||||
|
- kernel (verified by a shim-managed certificate)
|
||||||
|
- initramfs (verified by a shim-managed certificate)
|
||||||
|
|
||||||
|
### Quick start for the first boot
|
||||||
|
- Deploy the rootfs
|
||||||
|
|
||||||
|
- Boot up the target board
|
||||||
|
|
||||||
|
- Enter to BIOS setup and remove the enrolled certificates
|
||||||
|
* It is recommended to still turn on UEFI Secure Boot option if allowed.
|
||||||
|
|
||||||
|
- Exit BIOS setup and automatically reboot
|
||||||
|
|
||||||
|
- Manually launch a reboot via ctrl + alt + del again
|
||||||
|
* Otherwise, a misleading error message about the verification failure
|
||||||
|
will be displayed.
|
||||||
|
|
||||||
|
- Automatically boot to the boot option "Automatic Certificate Provision" in
|
||||||
|
grub boot menu.
|
||||||
|
|
||||||
|
- (Optional) Enter into BIOS setup to turn on UEFI Secure Boot option
|
||||||
|
|
||||||
|
- Boot to the system with the protection provided by UEFI and MOK Secure Boot
|
||||||
|
|
||||||
|
### Key Management
|
||||||
|
Refer to meta-signing-key/README.md for the initial cognition about key
|
||||||
|
management for UEFI Secure Boot.
|
||||||
|
|
||||||
|
Note that the sample key and user key are the concepts in the key signing
|
||||||
|
model according to the ownership and secrecy. In UEFI Secure Boot, a policy
|
||||||
|
object such as PK, KEK, DB and DBX is mapped to a key managed by the key
|
||||||
|
signing model.
|
||||||
|
|
||||||
|
#### Sample Keys
|
||||||
|
This feature, by default, use **the sample keys** to sign and verify images for
|
||||||
|
the purpose of development and demonstration. **Please ensure you know what your
|
||||||
|
risk is to use the sample keys in your product, because they are completely
|
||||||
|
public.**
|
||||||
|
|
||||||
|
The sample keys used for UEFI Secure Boot are centrally placed under
|
||||||
|
meta-signing-key/files/uefi_sb_keys/.
|
||||||
|
|
||||||
|
- PK.pem
|
||||||
|
The X509 certificate enrolled to UEFI BIOS, used to update/delete PK/KEK.
|
||||||
|
|
||||||
|
- PK.key
|
||||||
|
The private key corresponding to PK.pem, used to sign the EFI signature
|
||||||
|
list for PK/KEK enrollment.
|
||||||
|
|
||||||
|
- KEK.pem
|
||||||
|
The X509 certificate enrolled to UEFI BIOS, used to update/delete
|
||||||
|
DB/DBX.
|
||||||
|
|
||||||
|
- KEK.key
|
||||||
|
The private key corresponding to KEK.pem, used to sign the EFI signature
|
||||||
|
list for DB/DBX enrollment.
|
||||||
|
|
||||||
|
- DB.pem
|
||||||
|
The X509 certificate enrolled to UEFI BIOS, used to verify the images
|
||||||
|
directly loaded by UEFI BIOS.
|
||||||
|
|
||||||
|
- DB.key
|
||||||
|
The private key corresponding to DB.pem, used to sign the images directly
|
||||||
|
loaded by UEFI BIOS.
|
||||||
|
|
||||||
|
- DBX
|
||||||
|
This directory contains any number of X509 certificate enrolled to UEFI
|
||||||
|
BIOS, used to blacklist the revoked certificates. The revoked certificates
|
||||||
|
must be PEM-formatted.
|
||||||
|
|
||||||
|
The sample keys used for MOK Secure Boot are centrally placed under
|
||||||
|
`meta-signing-key/files/mok_sb_keys/`.
|
||||||
|
|
||||||
|
- shim_cert.pem
|
||||||
|
The X509 certificate embedded in shim, used to verify the images either
|
||||||
|
directly or indirectly loaded by shim.
|
||||||
|
|
||||||
|
- shim_cert.key
|
||||||
|
The private key corresponding to shim_cert.pem, used to sign the images
|
||||||
|
either directly or indirectly loaded by shim.
|
||||||
|
|
||||||
|
- vendor_cert.pem
|
||||||
|
Used in the same way as shim_cert.pem. In addition, vendor certificate
|
||||||
|
is the switch to enable shim verification protocol, which facilitates
|
||||||
|
the verification for the SELoader.
|
||||||
|
|
||||||
|
- vendor_cert.key
|
||||||
|
The private key corresponding to vendor_cert.pem, Same fuction as
|
||||||
|
shim_cert.key.
|
||||||
|
|
||||||
|
- vendor_dbx
|
||||||
|
This directory contains any number of X509 certificate embedded in shim,
|
||||||
|
used to blacklist the revoked certificates.
|
||||||
|
|
||||||
|
#### User Keys
|
||||||
|
Refer to meta-signing-key/README.md for the details about how to generate/use
|
||||||
|
the keys owned by the end user.
|
||||||
|
|
||||||
|
#### Automatic Certificate Provision
|
||||||
|
The certificate provision is required to enable UEFI Secure Boot. By default,
|
||||||
|
the target may be provisioned with the default certificates enrolled during the
|
||||||
|
manufacture.
|
||||||
|
|
||||||
|
In order to use the bootloader and kernel signed by the sample or self-owned
|
||||||
|
key to boot up the system, this feature provides a process of autmatic
|
||||||
|
certificate provison for the convenience. Refer to the instructions listed in
|
||||||
|
the section "Work Flow For The First Boot". The detailed descriptions are
|
||||||
|
given below.
|
||||||
|
|
||||||
|
##### Remove the enrolled certificates in BIOS setup
|
||||||
|
The LockDown.efi application is used to run the provision. However,
|
||||||
|
LockDown.efi cannot be launched if UEFI Secure Boot is already enabled. In
|
||||||
|
addition, the enrolled certificates may be not the ones the user hopes to use.
|
||||||
|
|
||||||
|
The provisioned certificates can be removed in BIOS setup. The detailed steps
|
||||||
|
may vary between the boards. Refer to BIOS manual for the details.
|
||||||
|
|
||||||
|
##### Launch the automatic provision
|
||||||
|
Lockdown.efi will automatically provision UEFI Secure Boot after removing the
|
||||||
|
the provisioned certificates in BIOS setup. More specifically, the PK, KEK,
|
||||||
|
DB and DBX (if any) will be enrolled and begin to take affect after a reboot.
|
||||||
|
|
||||||
|
##### Turn on UEFI Secure Boot option
|
||||||
|
If UEFI Secure Boot option is turned off, the user has to enter into BIOS setup
|
||||||
|
after provision to manually turn on the option.
|
||||||
|
|
||||||
|
If the option is already enabled when removing the enrolled certificates in
|
||||||
|
BIOS setup, this step can be ignored.
|
||||||
|
|
||||||
|
##### Re-trigger automatic provision
|
||||||
|
By default, the "Automatic Certificate Provision" option is hidden in boot
|
||||||
|
menu for the first boot. If the user would like to clear the certificates
|
||||||
|
provisioned by the "Automatic Certificate Provision" option in BIOS setup, this
|
||||||
|
hidden boot option will be shown in boot menu, allowing to re-trigger it when
|
||||||
|
necessary.
|
||||||
|
|
||||||
|
### Signing
|
||||||
|
By default, the build system uses DB.key to sign shim, and uses vendor_cert.key
|
||||||
|
to sign SELoader, grub, grub configuration file, kernel and initramfs image
|
||||||
|
during the build.
|
||||||
|
|
||||||
|
### Verficiation
|
||||||
|
|
||||||
|
#### UEFI Secure Boot Verification
|
||||||
|
UEFI BIOS will validate the integrity of shim bootloader with a certificate in
|
||||||
|
DB before running it.
|
||||||
|
|
||||||
|
#### Bootloader Verification
|
||||||
|
When the shim loads SELoader and SELoader loads grub, if both UEFI Secure Boot
|
||||||
|
and MOK Secure Boot are already enabled, the upper bootloader uses a list of
|
||||||
|
certificate to check the integrity of lower bootloader.
|
||||||
|
|
||||||
|
- Blacklist check
|
||||||
|
If the lower bootloader is signed with a key corresponding to a certificate
|
||||||
|
within any of a policy object below, the boot failure will occur.
|
||||||
|
|
||||||
|
* Vendor DBX
|
||||||
|
* DBX
|
||||||
|
* MokListX (MOK certificate blacklist)
|
||||||
|
|
||||||
|
- Whitelist check
|
||||||
|
If the lower bootloader is signed with a key corresponding to a certificate
|
||||||
|
within any of a policy object below, the boot success will occur.
|
||||||
|
|
||||||
|
* DB
|
||||||
|
* MokList (MOK certificate whitelist)
|
||||||
|
* Shim certificate (only for PE image)
|
||||||
|
* Vendor certificate
|
||||||
|
|
||||||
|
If the lower bootloader is not signed or signed by a key not corresponding to
|
||||||
|
any policy objects mentioned above, the boot failure will occur.
|
||||||
|
|
||||||
|
The benefit of these behaviors allow the end user to regulate the secure boot
|
||||||
|
even without the ownership of DB on Microsoft certificated hardware.
|
||||||
|
|
||||||
|
##### SELoader Verification
|
||||||
|
The SELoader is designed to authenticate the non-PE files, such as grub.cfg,
|
||||||
|
kernel (without EFI stub support) and initrd, which cannot be verified by
|
||||||
|
the verification protocol registered by the shim loader.
|
||||||
|
|
||||||
|
In order to conveniently authenticate the PE file with gBS->LoadImage()
|
||||||
|
and gBS->StartImage(), the SELoader hooks EFI Security2 Architectural
|
||||||
|
Protocol and employs verification protocol provided by the shim loader to
|
||||||
|
verify the PE file. If only UEFI Secure Boot is enabled, the SELoader just
|
||||||
|
simplily calls gBS->LoadImage() and gBS->StartImage() to allow UEFI BIOS
|
||||||
|
to verify the PE file.
|
||||||
|
|
||||||
|
The SELoader publishes MOK2 verification protocol which provides a flexible
|
||||||
|
interface to allow the bootloader to verify the file, file buffer or
|
||||||
|
memory buffer without knowing the file format.
|
||||||
|
|
||||||
|
In order to establish the chain of trust, the SELoader is required to be
|
||||||
|
signed by a private key corresponding to a DB certificate, the shim
|
||||||
|
certificate, the vendor certificate or a MOK certificate. The specific
|
||||||
|
key is determined by the secure boot scheme you will use.
|
||||||
|
|
||||||
|
See more details about the SELoader in its README file.
|
||||||
|
|
||||||
|
#### Grub Configuration File Verification
|
||||||
|
Grub can call the MOK2 verification protocol registered by the SELoader
|
||||||
|
to validate the integrity of grub configuration file before parsing it.
|
||||||
|
|
||||||
|
This protection prevents from tampering the grub configuration file from
|
||||||
|
disabling certains kernel security mechanism such as selinux, IMA and so on.
|
||||||
|
|
||||||
|
#### Kernel Verification
|
||||||
|
When SELoader loads the kernel image with the linux command, if both UEFI
|
||||||
|
Secure Boot and MOK Secure Boot are already enabled, grub will call the
|
||||||
|
verification protocol installed by SELoader to validate the kernel image.
|
||||||
|
|
||||||
|
Alternately, if grub loads the kernel image with the chainloader command,
|
||||||
|
if both UEFI Secure Boot and MOK Secure Boot are already enabled, grub will
|
||||||
|
call the verification protocol installed by shim to validate the kernel image.
|
||||||
|
|
||||||
|
By default, the kernel image is signed by vendor certificate and then signed
|
||||||
|
again to generate the .p7b signature file.
|
||||||
|
|
||||||
|
#### Initramfs Verification
|
||||||
|
When SELoader loads the kernel image with the initrd command, if both UEFI
|
||||||
|
Secure Boot and MOK Secure Boot are already enabled, grub will call the
|
||||||
|
verification protocol installed by SELoader to validate the initramfs image.
|
||||||
|
|
||||||
|
#### Verification Failure
|
||||||
|
Either situation will cause a failure of verification.
|
||||||
|
- A boot component is not signed.
|
||||||
|
- A boot component is signed by a key which doesn't correspond to any
|
||||||
|
certificate in whitelists such as DB and shim-managed certificates.
|
||||||
|
- A boot component is signed by a key which corresponds to a certificate in
|
||||||
|
blacklist such as DBX and shim-managed certificates in MOKX.
|
||||||
|
|
||||||
|
Each boot component may have different verification failure phenomenon.
|
||||||
|
- If SELoader fails signature check, UEFI BIOS boot manager will print an error
|
||||||
|
message about the image authentication failure.
|
||||||
|
- If grub fails signature check, an image authentication failure message is
|
||||||
|
printed and the system hangs.
|
||||||
|
- If a grub configuration file fails the signature check, an authentication
|
||||||
|
failure message is printed and grub hangs.
|
||||||
|
- If kernel image fails signature check, grub returns back to the boot menu.
|
||||||
|
- If initrd fails signature check, grub returns back to the boot menu.
|
||||||
|
|
||||||
|
### MOK Secure Boot and the shim bootloader
|
||||||
|
MOK (Machine Owner Key) Secure Boot is based on UEFI Secure Boot, adding
|
||||||
|
the shim bootloader to chainloader the second-stage bootloader
|
||||||
|
"SELoader" and eventually chainliader to the third-stage bootloader "grub".
|
||||||
|
|
||||||
|
[ Quoting: https://github.com/rhinstaller/shim ]
|
||||||
|
shim is a trivial EFI application that, when run, attempts to open and
|
||||||
|
execute another application. It will initially attempt to do this via the
|
||||||
|
standard EFI LoadImage() and StartImage() calls. If these fail (because secure
|
||||||
|
boot is enabled and the binary is not signed with an appropriate key, for
|
||||||
|
instance) it will then validate the binary against a built-in certificate. If
|
||||||
|
this succeeds and if the binary or signing key are not blacklisted then shim
|
||||||
|
will relocate and execute the binary.
|
||||||
|
|
||||||
|
shim will also install a protocol which permits the second-stage bootloader
|
||||||
|
to perform similar binary validation. This protocol has a GUID as described
|
||||||
|
in the shim.h header file and provides a single entry point. On 64-bit systems
|
||||||
|
this entry point expects to be called with SysV ABI rather than MSABI, and
|
||||||
|
so calls to it should not be wrapped.
|
||||||
|
[ End of Quote ]
|
||||||
|
|
||||||
|
In most cases, the hardware coming out of the factory is already provisioned
|
||||||
|
with a default certificate used to verify the bootloader and issued by
|
||||||
|
Microsoft Corporation UEFI CA 2011. This kind of hardware is so-called
|
||||||
|
Microsoft certificated hardware.
|
||||||
|
|
||||||
|
Obviously, this requirement needs a bootloader loaded by BIOS must be signed
|
||||||
|
by Microsoft. Microsoft provides the signing service (not free), but only
|
||||||
|
accept shim bootloader for Linux world. Refer to [Microsoft's signing policy](http://blogs.msdn.com/b/windows_hardware_certification/archive/2013/12/03/microsoft-uefi-ca-signing-policy-updates.aspx).
|
||||||
|
|
||||||
|
It is allowed to remove all default certificates and use the self-owned keys to
|
||||||
|
provision UEFI Secure Boot, but this is not practical for ODM/OEM devices
|
||||||
|
during the manufacture phrase. See the section "Out-of-box Experience".
|
||||||
|
|
||||||
|
For a good user experience, shim + SELoader + grub is an excellent combination
|
||||||
|
to handle Microsoft certificated hardware. With this model, SELoader and grub
|
||||||
|
are signed by a shim-managed certificate without being subject to the limit from
|
||||||
|
Microsoft's signing policy, and the manual provision is thus unnecessary.
|
||||||
|
|
||||||
|
#### mokutil and MOK Manager
|
||||||
|
mokutil is a tool to import or delete the machines owner keys stored in the
|
||||||
|
database of shim. mokutil creates the requests and MOK manager will be
|
||||||
|
automatically launched by shim as long as it detects the pending requests.
|
||||||
|
The physical present user will be prompted to run the operations corresponding
|
||||||
|
to the requests. Note the operation is required to be authenticated by MOK
|
||||||
|
management password set by mokutil.
|
||||||
|
|
||||||
|
Refer to mokutil man page for the detailed usages.
|
||||||
|
|
||||||
|
##### MOK Management Password
|
||||||
|
MOK management password is the authentication information to allow MOK manager
|
||||||
|
to grant the request regarding of MOK management. To set the password, run
|
||||||
|
mokutil with the option --password. In addition, there are 4 input methods to
|
||||||
|
provide the password. By default, mokutil prompts the user to input the
|
||||||
|
password and then wraps the password to sha256 password hash. For other 3
|
||||||
|
methods, refer to the uses of option --hash-file, --root-pw and --simple-hash.
|
||||||
|
|
||||||
|
##### Enroll the MOK certificate
|
||||||
|
Here is an example showing how to enroll a DER formatted X509 certificate to
|
||||||
|
the database of shim.
|
||||||
|
```
|
||||||
|
# mokutil --import <cert.cer>
|
||||||
|
```
|
||||||
|
where `<cert.cer>` is the MOK certificate corresponding to the private key used
|
||||||
|
to sign either grub or kernel.
|
||||||
|
|
||||||
|
To convert a PEM, for exmaple, the shim_cert.pem, to a DER formatted X509
|
||||||
|
certificate, type the command:
|
||||||
|
```
|
||||||
|
$ openssl x509 -in shim_cert.pem -inform PEM -out shim_cert.cer -outform DER
|
||||||
|
```
|
||||||
|
|
||||||
|
##### List the enrollment requests
|
||||||
|
The several enrollment requests can be submitted before system reboot. Run the
|
||||||
|
following command to check all enrollment requests.
|
||||||
|
```
|
||||||
|
# mokutil --list-new
|
||||||
|
```
|
||||||
|
|
||||||
|
##### Revoke the enrollment requests
|
||||||
|
Note the revocation operation will remove all enrollment requests.
|
||||||
|
```
|
||||||
|
# mokutil --revoke-import
|
||||||
|
```
|
||||||
|
|
||||||
|
##### Test the MOK certificate
|
||||||
|
If you cannot confirm whether a certificate has been enrolled or not, type the
|
||||||
|
following command for a check:
|
||||||
|
```
|
||||||
|
# mokutil --test-key <cert.cer>
|
||||||
|
```
|
||||||
|
|
||||||
|
##### Delete the MOK certificate
|
||||||
|
Removing an useless MOK certificate is also supported.
|
||||||
|
```
|
||||||
|
# mokutil --delete <cert.cer>
|
||||||
|
```
|
||||||
|
Refer to the options --list-delete and --revoke-delete to list and revoke the
|
||||||
|
MOKs.
|
||||||
|
|
||||||
|
##### Reset MOK certificates
|
||||||
|
This request will clear all enrolled MOK certificates.
|
||||||
|
```
|
||||||
|
# mokutil --reset
|
||||||
|
```
|
||||||
|
|
||||||
|
##### Disable/Enable MOK Secure Boot
|
||||||
|
MOK Secure Boot can be enabled or disabled regardless of the setting of UEFI
|
||||||
|
Secure Boot.
|
||||||
|
```
|
||||||
|
# mokutil --disable-validation // disable MOK Secure Boot
|
||||||
|
# mokutil --enable-validation // enable MOK Secure Boot
|
||||||
|
```
|
||||||
|
|
||||||
|
Note that MOK Secure Boot is based on UEFI Secure Boot. If UEFI Secure Boot
|
||||||
|
is disabled, MOK Secure Boot will be automatically inactive. Type the
|
||||||
|
following command to check the status of UEFI Secure Boot.
|
||||||
|
```
|
||||||
|
# mokutil --sb-state
|
||||||
|
```
|
||||||
|
|
||||||
|
##### Other options
|
||||||
|
Refer to the options --import-hash and --delete-hash to manage hash-based
|
||||||
|
signature. The options --pk, --kek, --db and --dbx are useful to check
|
||||||
|
the content of the policy objects used in UEFI Secure Boot.
|
||||||
|
|
||||||
|
##### Manage blacklist
|
||||||
|
All above mentioned are talking MOK which is acting as whitelist to
|
||||||
|
authenticate the verified image to launch. Actually, there is a contrary
|
||||||
|
policy object called MOKX, acting as blacklist to deny the untrusted
|
||||||
|
image to launch. Also, MOKX as blacklist is handled by shim prior to MOK
|
||||||
|
as whitelist.
|
||||||
|
|
||||||
|
For the management of blacklist, add the option --mokx with the following
|
||||||
|
options to change the operation target from MOK to the following options.
|
||||||
|
|
||||||
|
--list-enrolled
|
||||||
|
--test-key
|
||||||
|
--list-new
|
||||||
|
--list-delete
|
||||||
|
--import
|
||||||
|
--delete
|
||||||
|
--import-hash
|
||||||
|
--delete-hash
|
||||||
|
--reset
|
||||||
|
--revoke-import
|
||||||
|
--revoke-delete
|
||||||
|
|
||||||
|
##### Handle MOK Secure Boot Failure with MOK Manager
|
||||||
|
If either grub or SELoader is not signed or signed with an unauthorized
|
||||||
|
certificate, the shim will prompt the end user a UI called MOK manager to
|
||||||
|
guide the user to enroll the certificate or hash of the image.
|
||||||
|
|
||||||
|
The policy of the selection between digest and certificate for next step is
|
||||||
|
decided by whether the unauthorized grub or SELoader is signed or not.
|
||||||
|
|
||||||
|
If the grub or SELoader is not signed at all, you have to always select
|
||||||
|
the calculation of the digest based on the file. Note that once grub or SELoader
|
||||||
|
is updated and its digest is changed, you have to relaunch the MOK manager
|
||||||
|
to enroll the new digests.
|
||||||
|
|
||||||
|
If the grub or SELoader is signed by an unauthorized certificate, enrolling the
|
||||||
|
signing certificate is the preferred way. Copy the certificate to the boot
|
||||||
|
drive and then select the certificate in MOK manager. Note that the
|
||||||
|
certificate for the selection must be **DER formatted**.
|
||||||
|
|
||||||
|
If doing so, the unauthorized grub or SELoader will be verified successfully
|
||||||
|
after exiting MOK Manager.
|
||||||
|
|
||||||
|
### Grub Lockdown
|
||||||
|
In order to prevent from tampering the kernel command line or loading an
|
||||||
|
unsigned boot component, grub is locked if UEFI Secure Boot is enabled. In this
|
||||||
|
situation, the end user cannot enter into command or edit line via pressing 'c'
|
||||||
|
and 'e'.
|
||||||
|
|
||||||
|
If the user authentication is enabled, the access to command or edit line is
|
||||||
|
protected by a password. In this situation, grub is unlockable.
|
||||||
|
|
||||||
|
Rescue mode is always disabled as long as UEFI Secure Boot is enabled.
|
||||||
|
|
||||||
|
### Known Issues
|
||||||
|
- The 32-bit MOK Secure Boot is not validated. In other words, loading 32-bit
|
||||||
|
shim, MOK manager, grub and kernel is not supported.
|
||||||
|
|
||||||
|
### Reference
|
||||||
|
[OpenEmbedded layer for EFI secure boot features](https://github.com/jiazhang0/meta-efi-secure-boot)
|
||||||
16
meta-efi-secure-boot/conf/layer.conf
Normal file
16
meta-efi-secure-boot/conf/layer.conf
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
# We have a conf and classes directory, add to BBPATH
|
||||||
|
BBPATH .= ":${LAYERDIR}"
|
||||||
|
|
||||||
|
# We have recipes-* directories, add to BBFILES
|
||||||
|
BBFILES += "${LAYERDIR}/recipes-*/*/*.bb \
|
||||||
|
${LAYERDIR}/recipes-*/*/*.bbappend"
|
||||||
|
|
||||||
|
BBFILE_COLLECTIONS += "efi-secure-boot"
|
||||||
|
BBFILE_PATTERN_efi-secure-boot = "^${LAYERDIR}/"
|
||||||
|
BBFILE_PRIORITY_efi-secure-boot = "10"
|
||||||
|
|
||||||
|
LAYERDEPENDS_efi-secure-boot = "\
|
||||||
|
core \
|
||||||
|
openembedded-layer \
|
||||||
|
signing-key \
|
||||||
|
"
|
||||||
@@ -0,0 +1,28 @@
|
|||||||
|
DESCRIPTION = "EFI Secure Boot packages for secure-environment."
|
||||||
|
LICENSE = "MIT"
|
||||||
|
LIC_FILES_CHKSUM = "file://${COREBASE}/LICENSE;md5=4d92cd373abda3937c2bc47fbc49d690 \
|
||||||
|
file://${COREBASE}/meta/COPYING.MIT;md5=3da9cfbcb788c80a0384361b4de20420"
|
||||||
|
|
||||||
|
S = "${WORKDIR}"
|
||||||
|
|
||||||
|
ALLOW_EMPTY_${PN} = "1"
|
||||||
|
|
||||||
|
pkgs = " \
|
||||||
|
grub-efi \
|
||||||
|
efitools \
|
||||||
|
efibootmgr \
|
||||||
|
mokutil \
|
||||||
|
seloader \
|
||||||
|
shim \
|
||||||
|
"
|
||||||
|
|
||||||
|
RDEPENDS_${PN}_x86 = "${pkgs}"
|
||||||
|
RDEPENDS_${PN}_x86-64 = "${pkgs}"
|
||||||
|
|
||||||
|
kmods = " \
|
||||||
|
kernel-module-efivarfs \
|
||||||
|
kernel-module-efivars \
|
||||||
|
"
|
||||||
|
|
||||||
|
RRECOMMENDS_${PN}_x86 += "${kmods}"
|
||||||
|
RRECOMMENDS_${PN}_x86-64 += "${kmods}"
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
require efitools.inc
|
||||||
|
|
||||||
|
inherit native
|
||||||
|
|
||||||
|
DEPENDS_append = " gnu-efi-native"
|
||||||
|
|
||||||
|
EXTRA_OEMAKE_append = " \
|
||||||
|
INCDIR_PREFIX='${STAGING_DIR_NATIVE}' \
|
||||||
|
CRTPATH_PREFIX='${STAGING_DIR_NATIVE}' \
|
||||||
|
EXTRA_LDFLAGS='-Wl,-rpath,${libdir}' \
|
||||||
|
"
|
||||||
63
meta-efi-secure-boot/recipes-bsp/efitools/efitools.inc
Normal file
63
meta-efi-secure-boot/recipes-bsp/efitools/efitools.inc
Normal file
@@ -0,0 +1,63 @@
|
|||||||
|
SUMMARY = "Tools to support reading and manipulating the UEFI signature database"
|
||||||
|
DESCRIPTION = "\
|
||||||
|
From the EFI Tools package in the Linux user-space, it's now possible \
|
||||||
|
to read and manipulate the UEFI signatures database via the new \
|
||||||
|
efi-readvar and efi-updatevar commands. Aside from needing efitools \
|
||||||
|
1.4, the EFIVARFS file-system is also needed, which was only introduced \
|
||||||
|
in the Linux 3.8 kernel. \
|
||||||
|
"
|
||||||
|
|
||||||
|
LICENSE = "GPLv2"
|
||||||
|
LIC_FILES_CHKSUM = "file://COPYING;md5=e28f66b16cb46be47b20a4cdfe6e99a1"
|
||||||
|
|
||||||
|
SRC_URI = " \
|
||||||
|
git://git.kernel.org/pub/scm/linux/kernel/git/jejb/efitools.git \
|
||||||
|
file://Fix-for-the-cross-compilation.patch \
|
||||||
|
file://Kill-all-the-build-warning-caused-by-implicit-declar.patch \
|
||||||
|
file://Fix-the-wrong-dependency-for-blacklist.esl.patch \
|
||||||
|
file://LockDown-run-system-warm-reset-after-the-key-provisi.patch \
|
||||||
|
file://Allow-to-override-tools-for-target-build.patch \
|
||||||
|
file://Fix-help2man-failure.patch \
|
||||||
|
file://Don-t-build-PreLoader.efi.patch \
|
||||||
|
file://Reuse-xxdi.pl.patch \
|
||||||
|
file://Add-static-keyword-for-IsValidVariableHeader.patch \
|
||||||
|
"
|
||||||
|
|
||||||
|
SRCREV = "0649468475d20d8ca5634433c4912467cef3ce93"
|
||||||
|
PV = "1.7.0+git${SRCPV}"
|
||||||
|
|
||||||
|
PARALLEL_MAKE = ""
|
||||||
|
|
||||||
|
inherit perlnative
|
||||||
|
|
||||||
|
DEPENDS_append += "\
|
||||||
|
help2man-native openssl-native sbsigntool-native \
|
||||||
|
libfile-slurp-perl-native \
|
||||||
|
"
|
||||||
|
|
||||||
|
S = "${WORKDIR}/git"
|
||||||
|
|
||||||
|
EXTRA_OEMAKE = " \
|
||||||
|
HELP2MAN='${STAGING_BINDIR_NATIVE}/help2man' \
|
||||||
|
OPENSSL='${STAGING_BINDIR_NATIVE}/openssl' \
|
||||||
|
SBSIGN='${STAGING_BINDIR_NATIVE}/sbsign' \
|
||||||
|
OPENSSL_LIB='${STAGING_LIBDIR}' \
|
||||||
|
NM='${NM}' AR='${AR}' \
|
||||||
|
"
|
||||||
|
EXTRA_OEMAKE_append_x86 += " ARCH=ia32"
|
||||||
|
EXTRA_OEMAKE_append_x86-64 += " ARCH=x86_64"
|
||||||
|
|
||||||
|
# LDFLAGS is used by LD not CC, so remove '-Wl,'
|
||||||
|
LDFLAGS := "${@oe_filter_out('-Wl,', '${LDFLAGS}', d)}"
|
||||||
|
BUILD_LDFLAGS := "${@oe_filter_out('-Wl,', '${BUILD_LDFLAGS}', d)}"
|
||||||
|
|
||||||
|
do_compile_prepend() {
|
||||||
|
sed -i -e "1s:#!.*:#!/usr/bin/env nativeperl:" xxdi.pl
|
||||||
|
}
|
||||||
|
|
||||||
|
EFI_BOOT_PATH = "/boot/efi/EFI/BOOT"
|
||||||
|
FILES_${PN} += "${EFI_BOOT_PATH}"
|
||||||
|
|
||||||
|
do_install() {
|
||||||
|
oe_runmake install DESTDIR='${D}${base_prefix}'
|
||||||
|
}
|
||||||
@@ -0,0 +1,38 @@
|
|||||||
|
From 960a5fc7c58c875827797b6f4afed2684acc2cde Mon Sep 17 00:00:00 2001
|
||||||
|
From: Lans Zhang <jia.zhang@windriver.com>
|
||||||
|
Date: Sun, 12 Jun 2016 13:45:54 +0800
|
||||||
|
Subject: [PATCH] Add static keyword for IsValidVariableHeader()
|
||||||
|
|
||||||
|
Upstream-Status: Pending
|
||||||
|
|
||||||
|
GCC does not inline any functions when not optimizing (-O0 specified) unless
|
||||||
|
you specify "always_inline" attribute for the function.
|
||||||
|
|
||||||
|
By default, GCC complies with C89 standard for c code, which means
|
||||||
|
"inline" equals to "extern inline" and thus the definition is used only for
|
||||||
|
inlining with the assembly code actually generated.
|
||||||
|
|
||||||
|
Therefore, "static inline" is used for both purposes. If -O0 is specified,
|
||||||
|
GCC will generate the assembly code as long as the function is referred.
|
||||||
|
|
||||||
|
Signed-off-by: Lans Zhang <jia.zhang@windriver.com>
|
||||||
|
---
|
||||||
|
include/variableformat.h | 2 +-
|
||||||
|
1 files changed, 1 insertions(+), 1 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/include/variableformat.h b/include/variableformat.h
|
||||||
|
index 32cde05..45d0ebb 100644
|
||||||
|
--- a/include/variableformat.h
|
||||||
|
+++ b/include/variableformat.h
|
||||||
|
@@ -109,7 +109,7 @@ typedef struct {
|
||||||
|
|
||||||
|
#pragma pack()
|
||||||
|
|
||||||
|
-inline BOOLEAN
|
||||||
|
+static inline BOOLEAN
|
||||||
|
IsValidVariableHeader (VARIABLE_HEADER *vh) {
|
||||||
|
if (vh == NULL || vh->StartId != VARIABLE_DATA)
|
||||||
|
return FALSE;
|
||||||
|
--
|
||||||
|
1.7.1
|
||||||
|
|
||||||
@@ -0,0 +1,94 @@
|
|||||||
|
From 1613bae3a9760b3cdcbf8f43e750c475d69ad8bb Mon Sep 17 00:00:00 2001
|
||||||
|
From: Lans Zhang <jia.zhang@windriver.com>
|
||||||
|
Date: Wed, 23 Mar 2016 19:05:29 +0800
|
||||||
|
Subject: [PATCH] Allow to override tools for target build
|
||||||
|
|
||||||
|
Upstream-Status: Pending
|
||||||
|
|
||||||
|
These tools should use the ones from native build.
|
||||||
|
|
||||||
|
Signed-off-by: Lans Zhang <jia.zhang@windriver.com>
|
||||||
|
---
|
||||||
|
Make.rules | 22 +++++++++++++---------
|
||||||
|
Makefile | 4 ++--
|
||||||
|
2 files changed, 15 insertions(+), 11 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/Make.rules b/Make.rules
|
||||||
|
index 5e8cb82..4aa7650 100644
|
||||||
|
--- a/Make.rules
|
||||||
|
+++ b/Make.rules
|
||||||
|
@@ -34,6 +34,10 @@ AR = ar
|
||||||
|
OPENSSL = openssl
|
||||||
|
SBSIGN = sbsign
|
||||||
|
XXD = xxd
|
||||||
|
+SIGN_EFI_SIG_LIST ?= ./sign-efi-sig-list
|
||||||
|
+CERT_TO_EFI_SIG_LIST ?= ./cert-to-efi-sig-list
|
||||||
|
+CERT_TO_EFI_HASH_LIST ?= ./cert-to-efi-hash-list
|
||||||
|
+HASH_TO_EFI_SIG_LIST ?= ./hash-to-efi-sig-list
|
||||||
|
MYGUID = 11111111-2222-3333-4444-123456789abc
|
||||||
|
INSTALL = install
|
||||||
|
BINDIR = $(DESTDIR)/usr/bin
|
||||||
|
@@ -75,34 +79,34 @@ endif
|
||||||
|
$(XXD) -i $< > $@
|
||||||
|
|
||||||
|
%.hash: %.efi hash-to-efi-sig-list
|
||||||
|
- ./hash-to-efi-sig-list $< $@
|
||||||
|
+ $(HASH_TO_EFI_SIG_LIST) $< $@
|
||||||
|
|
||||||
|
%-blacklist.esl: %.crt cert-to-efi-sig-list
|
||||||
|
- ./cert-to-efi-sig-list $< $@
|
||||||
|
+ $(CERT_TO_EFI_SIG_LIST) $< $@
|
||||||
|
|
||||||
|
%-hash-blacklist.esl: %.crt cert-to-efi-hash-list
|
||||||
|
- ./cert-to-efi-hash-list $< $@
|
||||||
|
+ $(CERT_TO_EFI_HASH_LIST) $< $@
|
||||||
|
|
||||||
|
%.esl: %.crt cert-to-efi-sig-list
|
||||||
|
- ./cert-to-efi-sig-list -g $(MYGUID) $< $@
|
||||||
|
+ $(CERT_TO_EFI_SIG_LIST) -g $(MYGUID) $< $@
|
||||||
|
|
||||||
|
getcert = $(shell if [ "$(1)" = "PK" -o "$(1)" = "KEK" ]; then echo "-c PK.crt -k PK.key"; else echo "-c KEK.crt -k KEK.key"; fi)
|
||||||
|
getvar = $(shell if [ "$(1)" = "PK" -o "$(1)" = "KEK" ]; then echo $(1); else echo db; fi)
|
||||||
|
|
||||||
|
%.auth: %.esl PK.crt KEK.crt sign-efi-sig-list
|
||||||
|
- ./sign-efi-sig-list $(call getcert,$*) $(call getvar,$*) $< $@
|
||||||
|
+ $(SIGN_EFI_SIG_LIST) $(call getcert,$*) $(call getvar,$*) $< $@
|
||||||
|
|
||||||
|
%-update.auth: %.esl PK.crt KEK.crt sign-efi-sig-list
|
||||||
|
- ./sign-efi-sig-list -a $(call getcert,$*) $(call getvar,$*) $< $@
|
||||||
|
+ $(SIGN_EFI_SIG_LIST) -a $(call getcert,$*) $(call getvar,$*) $< $@
|
||||||
|
|
||||||
|
%-pkupdate.auth: %.esl PK.crt sign-efi-sig-list
|
||||||
|
- ./sign-efi-sig-list -a -c PK.crt -k PK.key $(call getvar,$*) $< $@
|
||||||
|
+ $(SIGN_EFI_SIG_LIST) -a -c PK.crt -k PK.key $(call getvar,$*) $< $@
|
||||||
|
|
||||||
|
%-blacklist.auth: %-blacklist.esl KEK.crt sign-efi-sig-list
|
||||||
|
- ./sign-efi-sig-list -a -c KEK.crt -k KEK.key dbx $< $@
|
||||||
|
+ $(SIGN_EFI_SIG_LIST) -a -c KEK.crt -k KEK.key dbx $< $@
|
||||||
|
|
||||||
|
%-pkblacklist.auth: %-blacklist.esl PK.crt sign-efi-sig-list
|
||||||
|
- ./sign-efi-sig-list -a -c PK.crt -k PK.key dbx $< $@
|
||||||
|
+ $(SIGN_EFI_SIG_LIST) -a -c PK.crt -k PK.key dbx $< $@
|
||||||
|
|
||||||
|
%.o: %.c
|
||||||
|
$(CC) $(INCDIR) $(cflags) $(cppflags) -c $< -o $@
|
||||||
|
diff --git a/Makefile b/Makefile
|
||||||
|
index 15fc944..c4e0081 100644
|
||||||
|
--- a/Makefile
|
||||||
|
+++ b/Makefile
|
||||||
|
@@ -66,10 +66,10 @@ noPK.esl:
|
||||||
|
> noPK.esl
|
||||||
|
|
||||||
|
noPK.auth: noPK.esl PK.crt sign-efi-sig-list
|
||||||
|
- ./sign-efi-sig-list -t "$(shell date --date='1 second' +'%Y-%m-%d %H:%M:%S')" -c PK.crt -k PK.key PK $< $@
|
||||||
|
+ $(SIGN_EFI_SIG_LIST) -t "$(shell date --date='1 second' +'%Y-%m-%d %H:%M:%S')" -c PK.crt -k PK.key PK $< $@
|
||||||
|
|
||||||
|
ms-%.esl: ms-%.crt cert-to-efi-sig-list
|
||||||
|
- ./cert-to-efi-sig-list -g $(MSGUID) $< $@
|
||||||
|
+ $(CERT_TO_EFI_SIG_LIST) -g $(MSGUID) $< $@
|
||||||
|
|
||||||
|
hashlist.h: HashTool.hash
|
||||||
|
cat $^ > /tmp/tmp.hash
|
||||||
|
--
|
||||||
|
1.9.1
|
||||||
|
|
||||||
@@ -0,0 +1,44 @@
|
|||||||
|
From e909a2d4777a6fd2644ff89361539db141c0a67f Mon Sep 17 00:00:00 2001
|
||||||
|
From: Lans Zhang <jia.zhang@windriver.com>
|
||||||
|
Date: Sat, 28 Jan 2017 13:42:28 +0800
|
||||||
|
Subject: [PATCH] Build DBX by default
|
||||||
|
|
||||||
|
Signed-off-by: Lans Zhang <jia.zhang@windriver.com>
|
||||||
|
---
|
||||||
|
Makefile | 6 +++---
|
||||||
|
1 file changed, 3 insertions(+), 3 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/Makefile b/Makefile
|
||||||
|
index a1fc538..7f767c8 100644
|
||||||
|
--- a/Makefile
|
||||||
|
+++ b/Makefile
|
||||||
|
@@ -26,7 +26,7 @@ include Make.rules
|
||||||
|
|
||||||
|
EFISIGNED = $(patsubst %.efi,%-signed.efi,$(EFIFILES))
|
||||||
|
|
||||||
|
-all: $(EFIFILES) $(BINARIES) $(MANPAGES) noPK.auth $(KEYAUTH) \
|
||||||
|
+all: $(EFIFILES) $(BINARIES) $(MANPAGES) noPK.auth $(KEYAUTH) DBX.auth \
|
||||||
|
$(KEYUPDATEAUTH) $(KEYBLACKLISTAUTH) $(KEYHASHBLACKLISTAUTH)
|
||||||
|
|
||||||
|
|
||||||
|
@@ -49,7 +49,7 @@ lib/asn1/libasn1.a lib/asn1/libasn1-efi.a: FORCE
|
||||||
|
|
||||||
|
.SUFFIXES: .crt
|
||||||
|
|
||||||
|
-.KEEP: PK.crt KEK.crt DB.crt PK.key KEK.key DB.key PK.esl DB.esl KEK.esl \
|
||||||
|
+.KEEP: PK.crt KEK.crt DB.crt DBX.crt PK.key KEK.key DB.key PK.esl DB.esl KEK.esl DBX.esl \
|
||||||
|
$(EFIFILES)
|
||||||
|
|
||||||
|
LockDown.o: PK.h KEK.h DB.h DBX.h
|
||||||
|
@@ -116,7 +116,7 @@ flash-var: flash-var.o lib/lib.a
|
||||||
|
$(CC) $(ARCH3264) -o $@ $< lib/lib.a
|
||||||
|
|
||||||
|
clean:
|
||||||
|
- rm -f PK.* KEK.* DB.* $(EFIFILES) $(EFISIGNED) $(BINARIES) *.o *.so
|
||||||
|
+ rm -f PK.* KEK.* DB.* DBX.* $(EFIFILES) $(EFISIGNED) $(BINARIES) *.o *.so
|
||||||
|
rm -f noPK.*
|
||||||
|
rm -f doc/*.1
|
||||||
|
$(MAKE) -C lib clean
|
||||||
|
--
|
||||||
|
2.7.4
|
||||||
|
|
||||||
@@ -0,0 +1,40 @@
|
|||||||
|
From 95e167f432f1a6d8c96aeca73871122806007c9f Mon Sep 17 00:00:00 2001
|
||||||
|
From: Lans Zhang <jia.zhang@windriver.com>
|
||||||
|
Date: Thu, 28 Apr 2016 11:21:33 +0800
|
||||||
|
Subject: [PATCH] Don't build PreLoader.efi
|
||||||
|
|
||||||
|
Upstream-Status: Pending
|
||||||
|
|
||||||
|
The upstream has an obvious build failure:
|
||||||
|
| PreLoader.c:45:2: error: too few arguments to function 'security_policy_install'
|
||||||
|
| status = security_policy_install();
|
||||||
|
| ^
|
||||||
|
| In file included from PreLoader.c:14:0:
|
||||||
|
| /buildarea3/jzhang0/projects/wrl8/intel-x86-64-gwp-scp/bitbake_build/tmp/work/x86_64-linux/efitools-native/1.7.0+gitAUTOINC+20a8fdc4ec-r0/git/include/security_policy.h:4:1: note: declared here
|
||||||
|
| security_policy_install(BOOLEAN (*override)(void), POLICY_FUNCTION allow, POLICY_FUNCTION deny);
|
||||||
|
| ^
|
||||||
|
|
||||||
|
We are waiting for the upstream fix and remove this workaround in next
|
||||||
|
refresh.
|
||||||
|
|
||||||
|
Signed-off-by: Lans Zhang <jia.zhang@windriver.com>
|
||||||
|
---
|
||||||
|
Makefile | 2 +-
|
||||||
|
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||||
|
|
||||||
|
diff --git a/Makefile b/Makefile
|
||||||
|
index b3bb73a..da363a6 100644
|
||||||
|
--- a/Makefile
|
||||||
|
+++ b/Makefile
|
||||||
|
@@ -5,7 +5,7 @@ BINARIES = cert-to-efi-sig-list sig-list-to-certs sign-efi-sig-list \
|
||||||
|
flash-var
|
||||||
|
|
||||||
|
ifeq ($(ARCH),x86_64)
|
||||||
|
-EFIFILES += PreLoader.efi
|
||||||
|
+#EFIFILES += PreLoader.efi
|
||||||
|
endif
|
||||||
|
|
||||||
|
MSGUID = 77FA9ABD-0359-4D32-BD60-28F4E78F784B
|
||||||
|
--
|
||||||
|
1.9.1
|
||||||
|
|
||||||
@@ -0,0 +1,193 @@
|
|||||||
|
From ab2eb06c1271e46e07add5a0b0a444353d45e055 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Lans Zhang <jia.zhang@windriver.com>
|
||||||
|
Date: Tue, 15 Mar 2016 21:28:33 +0800
|
||||||
|
Subject: [PATCH] Fix for the cross compilation
|
||||||
|
|
||||||
|
Upstream-Status: Pending
|
||||||
|
|
||||||
|
Signed-off-by: Lans Zhang <jia.zhang@windriver.com>
|
||||||
|
---
|
||||||
|
Make.rules | 52 +++++++++++++++++++++++++++++-----------------------
|
||||||
|
Makefile | 14 +++++++-------
|
||||||
|
2 files changed, 36 insertions(+), 30 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/Make.rules b/Make.rules
|
||||||
|
index 88d5481..7e89332 100644
|
||||||
|
--- a/Make.rules
|
||||||
|
+++ b/Make.rules
|
||||||
|
@@ -13,21 +13,27 @@ ARCH3264 =
|
||||||
|
else
|
||||||
|
$(error unknown architecture $(ARCH))
|
||||||
|
endif
|
||||||
|
-INCDIR = -I$(TOPDIR)include/ -I/usr/include/efi -I/usr/include/efi/$(ARCH) -I/usr/include/efi/protocol
|
||||||
|
-CPPFLAGS = -DCONFIG_$(ARCH)
|
||||||
|
-CFLAGS = -O2 $(ARCH3264) -fpic -Wall -fshort-wchar -fno-strict-aliasing -fno-merge-constants -fno-stack-protector -ffreestanding -fno-stack-check
|
||||||
|
-LDFLAGS = -nostdlib
|
||||||
|
+INCDIR = -I$(TOPDIR)include/ -I$(INCDIR_PREFIX)/usr/include/efi -I$(INCDIR_PREFIX)/usr/include/efi/$(ARCH) -I$(INCDIR_PREFIX)/usr/include/efi/protocol
|
||||||
|
+cppflags = -DCONFIG_$(ARCH)
|
||||||
|
+cflags = -O2 $(ARCH3264) -fpic -Wall -fshort-wchar -fno-strict-aliasing -fno-merge-constants -fno-stack-protector -ffreestanding -fno-stack-check $(CFLAGS)
|
||||||
|
+ldflags = -nostdlib $(LDFLAGS)
|
||||||
|
CRTOBJ = crt0-efi-$(ARCH).o
|
||||||
|
CRTPATHS = /lib /lib64 /lib/efi /lib64/efi /usr/lib /usr/lib64 /usr/lib/efi /usr/lib64/efi
|
||||||
|
-CRTPATH = $(shell for f in $(CRTPATHS); do if [ -e $$f/$(CRTOBJ) ]; then echo $$f; break; fi; done)
|
||||||
|
+CRTPATH = $(shell for f in $(CRTPATHS); do if [ -e $(CRTPATH_PREFIX)/$$f/$(CRTOBJ) ]; then echo $(CRTPATH_PREFIX)/$$f; break; fi; done)
|
||||||
|
CRTOBJS = $(CRTPATH)/$(CRTOBJ)
|
||||||
|
# there's a bug in the gnu tools ... the .reloc section has to be
|
||||||
|
# aligned otherwise the file alignment gets screwed up
|
||||||
|
LDSCRIPT = elf_$(ARCH)_efi.lds
|
||||||
|
-LDFLAGS += -shared -Bsymbolic $(CRTOBJS) -L $(CRTPATH) -T $(LDSCRIPT)
|
||||||
|
+ldflags += -shared -Bsymbolic $(CRTOBJS) -L $(CRTPATH) -T $(LDSCRIPT)
|
||||||
|
+ldflags_openssl = $(addprefix -L$(CRTPATH_PREFIX),$(CRTPATHS))
|
||||||
|
LOADLIBES = -lefi -lgnuefi $(shell $(CC) $(ARCH3264) -print-libgcc-file-name)
|
||||||
|
FORMAT = --target=efi-app-$(ARCH)
|
||||||
|
OBJCOPY = objcopy
|
||||||
|
+NM = nm
|
||||||
|
+AR = ar
|
||||||
|
+OPENSSL = openssl
|
||||||
|
+SBSIGN = sbsign
|
||||||
|
+XXD = xxd
|
||||||
|
MYGUID = 11111111-2222-3333-4444-123456789abc
|
||||||
|
INSTALL = install
|
||||||
|
BINDIR = $(DESTDIR)/usr/bin
|
||||||
|
@@ -36,23 +42,23 @@ EFIDIR = $(DESTDIR)/usr/share/efitools/efi
|
||||||
|
DOCDIR = $(DESTDIR)/usr/share/efitools
|
||||||
|
|
||||||
|
# globally use EFI calling conventions (requires gcc >= 4.7)
|
||||||
|
-CFLAGS += -DGNU_EFI_USE_MS_ABI
|
||||||
|
+cflags += -DGNU_EFI_USE_MS_ABI
|
||||||
|
|
||||||
|
ifeq ($(ARCH),x86_64)
|
||||||
|
- CFLAGS += -DEFI_FUNCTION_WRAPPER -mno-red-zone
|
||||||
|
+ cflags += -DEFI_FUNCTION_WRAPPER -mno-red-zone
|
||||||
|
endif
|
||||||
|
|
||||||
|
ifeq ($(ARCH),ia32)
|
||||||
|
- CFLAGS += -mno-red-zone
|
||||||
|
+ cflags += -mno-red-zone
|
||||||
|
endif
|
||||||
|
|
||||||
|
ifeq ($(ARCH),arm)
|
||||||
|
- LDFLAGS += --defsym=EFI_SUBSYSTEM=0x0a
|
||||||
|
+ ldflags += --defsym=EFI_SUBSYSTEM=0x0a
|
||||||
|
FORMAT = -O binary
|
||||||
|
endif
|
||||||
|
|
||||||
|
ifeq ($(ARCH),aarch64)
|
||||||
|
- LDFLAGS += --defsym=EFI_SUBSYSTEM=0x0a
|
||||||
|
+ ldflags += --defsym=EFI_SUBSYSTEM=0x0a
|
||||||
|
FORMAT = -O binary
|
||||||
|
endif
|
||||||
|
|
||||||
|
@@ -61,12 +67,12 @@ endif
|
||||||
|
-j .rel -j .rela -j .rel.* -j .rela.* -j .rel* -j .rela* \
|
||||||
|
-j .reloc $(FORMAT) $*.so $@
|
||||||
|
%.so: %.o
|
||||||
|
- $(LD) $(LDFLAGS) $^ -o $@ $(LOADLIBES)
|
||||||
|
+ $(LD) $(ldflags) $^ -o $@ $(LOADLIBES)
|
||||||
|
# check we have no undefined symbols
|
||||||
|
- nm -D $@ | grep ' U ' && exit 1 || exit 0
|
||||||
|
+ ${NM} -D $@ | grep ' U ' && exit 1 || exit 0
|
||||||
|
|
||||||
|
%.h: %.auth
|
||||||
|
- ./xxdi.pl $< > $@
|
||||||
|
+ $(XXD) -i $< > $@
|
||||||
|
|
||||||
|
%.hash: %.efi hash-to-efi-sig-list
|
||||||
|
./hash-to-efi-sig-list $< $@
|
||||||
|
@@ -99,28 +105,28 @@ getvar = $(shell if [ "$(1)" = "PK" -o "$(1)" = "KEK" ]; then echo $(1); else ec
|
||||||
|
./sign-efi-sig-list -a -c PK.crt -k PK.key dbx $< $@
|
||||||
|
|
||||||
|
%.o: %.c
|
||||||
|
- $(CC) $(INCDIR) $(CFLAGS) $(CPPFLAGS) -c $< -o $@
|
||||||
|
+ $(CC) $(INCDIR) $(cflags) $(cppflags) -c $< -o $@
|
||||||
|
|
||||||
|
%.efi.o: %.c
|
||||||
|
- $(CC) $(INCDIR) $(CFLAGS) $(CPPFLAGS) -fno-toplevel-reorder -DBUILD_EFI -c $< -o $@
|
||||||
|
+ $(CC) $(INCDIR) $(cflags) $(cppflags) -fno-toplevel-reorder -DBUILD_EFI -c $< -o $@
|
||||||
|
|
||||||
|
%.efi.s: %.c
|
||||||
|
- $(CC) -S $(INCDIR) $(CFLAGS) $(CPPFLAGS) -fno-toplevel-reorder -DBUILD_EFI -c $< -o $@
|
||||||
|
+ $(CC) -S $(INCDIR) $(cflags) $(cppflags) -fno-toplevel-reorder -DBUILD_EFI -c $< -o $@
|
||||||
|
|
||||||
|
%.crt:
|
||||||
|
- openssl req -new -x509 -newkey rsa:2048 -subj "/CN=$*/" -keyout $*.key -out $@ -days 3650 -nodes -sha256
|
||||||
|
+ $(OPENSSL) req -new -x509 -newkey rsa:2048 -subj "/CN=$*/" -keyout $*.key -out $@ -days 3650 -nodes -sha256
|
||||||
|
|
||||||
|
%.cer: %.crt
|
||||||
|
- openssl x509 -in $< -out $@ -outform DER
|
||||||
|
+ $(OPENSSL) x509 -in $< -out $@ -outform DER
|
||||||
|
|
||||||
|
%-subkey.csr:
|
||||||
|
- openssl req -new -newkey rsa:2048 -keyout $*-subkey.key -subj "/CN=Subkey $* of KEK/" -out $@ -nodes
|
||||||
|
+ $(OPENSSL) req -new -newkey rsa:2048 -keyout $*-subkey.key -subj "/CN=Subkey $* of KEK/" -out $@ -nodes
|
||||||
|
|
||||||
|
%-subkey.crt: %-subkey.csr KEK.crt
|
||||||
|
- openssl x509 -req -in $< -CA DB.crt -CAkey DB.key -set_serial 1 -out $@ -days 365
|
||||||
|
+ $(OPENSSL) x509 -req -in $< -CA DB.crt -CAkey DB.key -set_serial 1 -out $@ -days 365
|
||||||
|
|
||||||
|
%-signed.efi: %.efi DB.crt
|
||||||
|
- sbsign --key DB.key --cert DB.crt --output $@ $<
|
||||||
|
+ $(SBSIGN) --key DB.key --cert DB.crt --output $@ $<
|
||||||
|
|
||||||
|
##
|
||||||
|
# No need for KEK signing
|
||||||
|
@@ -129,7 +135,7 @@ getvar = $(shell if [ "$(1)" = "PK" -o "$(1)" = "KEK" ]; then echo $(1); else ec
|
||||||
|
# sbsign --key KEK.key --cert KEK.crt --output $@ $<
|
||||||
|
|
||||||
|
%.a:
|
||||||
|
- ar rcv $@ $^
|
||||||
|
+ $(AR) rcv $@ $^
|
||||||
|
|
||||||
|
doc/%.1: doc/%.1.in %
|
||||||
|
$(HELP2MAN) --no-info -i $< -o $@ ./$*
|
||||||
|
diff --git a/Makefile b/Makefile
|
||||||
|
index 774ee0a..46e4620 100644
|
||||||
|
--- a/Makefile
|
||||||
|
+++ b/Makefile
|
||||||
|
@@ -73,7 +73,7 @@ ms-%.esl: ms-%.crt cert-to-efi-sig-list
|
||||||
|
|
||||||
|
hashlist.h: HashTool.hash
|
||||||
|
cat $^ > /tmp/tmp.hash
|
||||||
|
- ./xxdi.pl /tmp/tmp.hash > $@
|
||||||
|
+ $(XXD) -i /tmp/tmp.hash > $@
|
||||||
|
rm -f /tmp/tmp.hash
|
||||||
|
|
||||||
|
|
||||||
|
@@ -88,28 +88,28 @@ HelloWorld.so: lib/lib-efi.a
|
||||||
|
ShimReplace.so: lib/lib-efi.a
|
||||||
|
|
||||||
|
cert-to-efi-sig-list: cert-to-efi-sig-list.o lib/lib.a
|
||||||
|
- $(CC) $(ARCH3264) -o $@ $< -lcrypto lib/lib.a
|
||||||
|
+ $(CC) $(ARCH3264) -o $@ $< $(ldflags_openssl) $(EXTRA_LDFLAGS) -lcrypto lib/lib.a
|
||||||
|
|
||||||
|
sig-list-to-certs: sig-list-to-certs.o lib/lib.a
|
||||||
|
- $(CC) $(ARCH3264) -o $@ $< -lcrypto lib/lib.a
|
||||||
|
+ $(CC) $(ARCH3264) -o $@ $< $(ldflags_openssl) $(EXTRA_LDFLAGS) -lcrypto lib/lib.a
|
||||||
|
|
||||||
|
sign-efi-sig-list: sign-efi-sig-list.o lib/lib.a
|
||||||
|
- $(CC) $(ARCH3264) -o $@ $< -lcrypto lib/lib.a
|
||||||
|
+ $(CC) $(ARCH3264) -o $@ $< $(ldflags_openssl) $(EXTRA_LDFLAGS) -lcrypto lib/lib.a
|
||||||
|
|
||||||
|
hash-to-efi-sig-list: hash-to-efi-sig-list.o lib/lib.a
|
||||||
|
$(CC) $(ARCH3264) -o $@ $< lib/lib.a
|
||||||
|
|
||||||
|
cert-to-efi-hash-list: cert-to-efi-hash-list.o lib/lib.a
|
||||||
|
- $(CC) $(ARCH3264) -o $@ $< -lcrypto lib/lib.a
|
||||||
|
+ $(CC) $(ARCH3264) -o $@ $< $(ldflags_openssl) $(EXTRA_LDFLAGS) -lcrypto lib/lib.a
|
||||||
|
|
||||||
|
efi-keytool: efi-keytool.o lib/lib.a
|
||||||
|
$(CC) $(ARCH3264) -o $@ $< lib/lib.a
|
||||||
|
|
||||||
|
efi-readvar: efi-readvar.o lib/lib.a
|
||||||
|
- $(CC) $(ARCH3264) -o $@ $< -lcrypto lib/lib.a
|
||||||
|
+ $(CC) $(ARCH3264) -o $@ $< $(ldflags_openssl) $(EXTRA_LDFLAGS) -lcrypto lib/lib.a
|
||||||
|
|
||||||
|
efi-updatevar: efi-updatevar.o lib/lib.a
|
||||||
|
- $(CC) $(ARCH3264) -o $@ $< -lcrypto lib/lib.a
|
||||||
|
+ $(CC) $(ARCH3264) -o $@ $< $(ldflags_openssl) $(EXTRA_LDFLAGS) -lcrypto lib/lib.a
|
||||||
|
|
||||||
|
flash-var: flash-var.o lib/lib.a
|
||||||
|
$(CC) $(ARCH3264) -o $@ $< lib/lib.a
|
||||||
|
--
|
||||||
|
1.9.1
|
||||||
|
|
||||||
@@ -0,0 +1,28 @@
|
|||||||
|
From f2e4ff4e63f4a5f8a4452c970ca271091eeaec7d Mon Sep 17 00:00:00 2001
|
||||||
|
From: Lans Zhang <jia.zhang@windriver.com>
|
||||||
|
Date: Sun, 18 Jun 2017 23:35:09 +0800
|
||||||
|
Subject: [PATCH] Fix help2man error
|
||||||
|
|
||||||
|
This issue may be caused by the poky compiler.
|
||||||
|
|
||||||
|
Signed-off-by: Lans Zhang <jia.zhang@windriver.com>
|
||||||
|
---
|
||||||
|
Make.rules | 4 +++-
|
||||||
|
1 file changed, 3 insertions(+), 1 deletion(-)
|
||||||
|
|
||||||
|
diff --git a/Make.rules b/Make.rules
|
||||||
|
index 38c7a22..bda5518 100644
|
||||||
|
--- a/Make.rules
|
||||||
|
+++ b/Make.rules
|
||||||
|
@@ -140,5 +140,7 @@ getvar = $(shell if [ "$(1)" = "PK" -o "$(1)" = "KEK" ]; then echo $(1); else ec
|
||||||
|
%.a:
|
||||||
|
$(AR) rcv $@ $^
|
||||||
|
|
||||||
|
+HELP2MAN_PROG_PREFIX ?= .
|
||||||
|
+
|
||||||
|
doc/%.1: doc/%.1.in %
|
||||||
|
- $(HELP2MAN) --no-discard-stderr --no-info -i $< -o $@ ./$*
|
||||||
|
+ $(HELP2MAN) --no-discard-stderr --no-info -i $< -o $@ $(HELP2MAN_PROG_PREFIX)/$*
|
||||||
|
--
|
||||||
|
2.7.5
|
||||||
|
|
||||||
@@ -0,0 +1,25 @@
|
|||||||
|
From 546b8c36301bdcf540b3b027fd25baa9cff2abdc Mon Sep 17 00:00:00 2001
|
||||||
|
From: Lans Zhang <jia.zhang@windriver.com>
|
||||||
|
Date: Wed, 23 Mar 2016 19:44:51 +0800
|
||||||
|
Subject: [PATCH] Fix help2man failure
|
||||||
|
|
||||||
|
Add --no-discard-stderr to work around the error.
|
||||||
|
|
||||||
|
Signed-off-by: Lans Zhang <jia.zhang@windriver.com>
|
||||||
|
---
|
||||||
|
Make.rules | 2 +-
|
||||||
|
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||||
|
|
||||||
|
diff --git a/Make.rules b/Make.rules
|
||||||
|
index 4aa7650..21926b0 100644
|
||||||
|
--- a/Make.rules
|
||||||
|
+++ b/Make.rules
|
||||||
|
@@ -142,4 +142,4 @@ getvar = $(shell if [ "$(1)" = "PK" -o "$(1)" = "KEK" ]; then echo $(1); else ec
|
||||||
|
$(AR) rcv $@ $^
|
||||||
|
|
||||||
|
doc/%.1: doc/%.1.in %
|
||||||
|
- $(HELP2MAN) --no-info -i $< -o $@ ./$*
|
||||||
|
+ $(HELP2MAN) --no-discard-stderr --no-info -i $< -o $@ ./$*
|
||||||
|
--
|
||||||
|
1.9.1
|
||||||
|
|
||||||
@@ -0,0 +1,28 @@
|
|||||||
|
From 52228c24af681463d73d5bd8454872b3e811855b Mon Sep 17 00:00:00 2001
|
||||||
|
From: Lans Zhang <jia.zhang@windriver.com>
|
||||||
|
Date: Tue, 15 Mar 2016 21:07:31 +0800
|
||||||
|
Subject: [PATCH] Fix the wrong dependency for %-blacklist.esl
|
||||||
|
|
||||||
|
Upstream-Status: Pending
|
||||||
|
|
||||||
|
Signed-off-by: Lans Zhang <jia.zhang@windriver.com>
|
||||||
|
---
|
||||||
|
Make.rules | 2 +-
|
||||||
|
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||||
|
|
||||||
|
diff --git a/Make.rules b/Make.rules
|
||||||
|
index 48b02e4..08a2489 100644
|
||||||
|
--- a/Make.rules
|
||||||
|
+++ b/Make.rules
|
||||||
|
@@ -77,7 +77,7 @@ endif
|
||||||
|
%.hash: %.efi hash-to-efi-sig-list
|
||||||
|
./hash-to-efi-sig-list $< $@
|
||||||
|
|
||||||
|
-%-blacklist.esl: %.crt cert-to-efi-hash-list
|
||||||
|
+%-blacklist.esl: %.crt cert-to-efi-sig-list
|
||||||
|
./cert-to-efi-sig-list $< $@
|
||||||
|
|
||||||
|
%-hash-blacklist.esl: %.crt cert-to-efi-hash-list
|
||||||
|
--
|
||||||
|
1.9.1
|
||||||
|
|
||||||
@@ -0,0 +1,80 @@
|
|||||||
|
From 872a9d96386b819d2c5fd7581d2bdaf7ea61a5f8 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Lans Zhang <jia.zhang@windriver.com>
|
||||||
|
Date: Tue, 15 Mar 2016 17:12:24 +0800
|
||||||
|
Subject: [PATCH] Kill all the build warning caused by implicit declaration of
|
||||||
|
function
|
||||||
|
|
||||||
|
Upstream-Status: Pending
|
||||||
|
|
||||||
|
Signed-off-by: Lans Zhang <jia.zhang@windriver.com>
|
||||||
|
---
|
||||||
|
Loader.c | 1 +
|
||||||
|
cert-to-efi-hash-list.c | 2 +-
|
||||||
|
flash-var.c | 2 ++
|
||||||
|
lib/pecoff.c | 1 +
|
||||||
|
sign-efi-sig-list.c | 2 ++
|
||||||
|
5 files changed, 7 insertions(+), 1 deletion(-)
|
||||||
|
|
||||||
|
diff --git a/Loader.c b/Loader.c
|
||||||
|
index 1f9201a..044469a 100644
|
||||||
|
--- a/Loader.c
|
||||||
|
+++ b/Loader.c
|
||||||
|
@@ -9,6 +9,7 @@
|
||||||
|
#include <efi.h>
|
||||||
|
#include <efilib.h>
|
||||||
|
|
||||||
|
+#include <execute.h>
|
||||||
|
#include <simple_file.h>
|
||||||
|
#include <pecoff.h>
|
||||||
|
#include <sha256.h>
|
||||||
|
diff --git a/cert-to-efi-hash-list.c b/cert-to-efi-hash-list.c
|
||||||
|
index d4484f9..3792553 100644
|
||||||
|
--- a/cert-to-efi-hash-list.c
|
||||||
|
+++ b/cert-to-efi-hash-list.c
|
||||||
|
@@ -3,7 +3,7 @@
|
||||||
|
*
|
||||||
|
* see COPYING file
|
||||||
|
*/
|
||||||
|
-
|
||||||
|
+#define _GNU_SOURCE
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
#define __STDC_VERSION__ 199901L
|
||||||
|
diff --git a/flash-var.c b/flash-var.c
|
||||||
|
index aa10ae6..10429bc 100644
|
||||||
|
--- a/flash-var.c
|
||||||
|
+++ b/flash-var.c
|
||||||
|
@@ -1,3 +1,5 @@
|
||||||
|
+#define _GNU_SOURCE
|
||||||
|
+
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
diff --git a/lib/pecoff.c b/lib/pecoff.c
|
||||||
|
index 26d9dcf..10b898a 100644
|
||||||
|
--- a/lib/pecoff.c
|
||||||
|
+++ b/lib/pecoff.c
|
||||||
|
@@ -59,6 +59,7 @@
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
+#include <execute.h>
|
||||||
|
#include <pecoff.h>
|
||||||
|
#include <guid.h>
|
||||||
|
#include <simple_file.h>
|
||||||
|
diff --git a/sign-efi-sig-list.c b/sign-efi-sig-list.c
|
||||||
|
index e19ef97..5abcf27 100644
|
||||||
|
--- a/sign-efi-sig-list.c
|
||||||
|
+++ b/sign-efi-sig-list.c
|
||||||
|
@@ -3,6 +3,8 @@
|
||||||
|
*
|
||||||
|
* see COPYING file
|
||||||
|
*/
|
||||||
|
+#define _GNU_SOURCE
|
||||||
|
+
|
||||||
|
#include <stdint.h>
|
||||||
|
#define __STDC_VERSION__ 199901L
|
||||||
|
#include <efi.h>
|
||||||
|
--
|
||||||
|
1.9.1
|
||||||
|
|
||||||
@@ -0,0 +1,47 @@
|
|||||||
|
From e259aecc645c6dd4c194a64d607124cd5a714f9a Mon Sep 17 00:00:00 2001
|
||||||
|
From: Lans Zhang <jia.zhang@windriver.com>
|
||||||
|
Date: Wed, 15 Feb 2017 14:52:07 +0800
|
||||||
|
Subject: [PATCH] LockDown: disable the entrance into BIOS setup to re-enable
|
||||||
|
secure boot
|
||||||
|
|
||||||
|
In most cases, this step is not necessary.
|
||||||
|
|
||||||
|
Signed-off-by: Lans Zhang <jia.zhang@windriver.com>
|
||||||
|
---
|
||||||
|
LockDown.c | 9 +++++++--
|
||||||
|
1 file changed, 7 insertions(+), 2 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/LockDown.c b/LockDown.c
|
||||||
|
index 13c626f..fbde3f2 100644
|
||||||
|
--- a/LockDown.c
|
||||||
|
+++ b/LockDown.c
|
||||||
|
@@ -20,6 +20,11 @@ efi_main (EFI_HANDLE image, EFI_SYSTEM_TABLE *systab)
|
||||||
|
EFI_STATUS efi_status;
|
||||||
|
UINT8 SecureBoot, SetupMode;
|
||||||
|
UINTN DataSize = sizeof(SetupMode);
|
||||||
|
+ /* This controls whether it is required to enter into BIOS setup in
|
||||||
|
+ * order to re-enable UEFI secure boot. This operation is unnecessary
|
||||||
|
+ * in most cases.
|
||||||
|
+ */
|
||||||
|
+ UINTN NeedSetAttempt = 0;
|
||||||
|
|
||||||
|
InitializeLib(image, systab);
|
||||||
|
|
||||||
|
@@ -110,12 +115,12 @@ efi_main (EFI_HANDLE image, EFI_SYSTEM_TABLE *systab)
|
||||||
|
* UEFI secure boot in BIOS setup.
|
||||||
|
*/
|
||||||
|
Print(L"Prepare to execute system warm reset after 3 seconds ...\n");
|
||||||
|
- if (!SecureBoot)
|
||||||
|
+ if (NeedSetAttempt && !SecureBoot)
|
||||||
|
Print(L"After warm reset, enter to BIOS setup to enable UEFI Secure Boot.\n");
|
||||||
|
|
||||||
|
BS->Stall(3000000);
|
||||||
|
|
||||||
|
- if (!SecureBoot)
|
||||||
|
+ if (NeedSetAttempt && !SecureBoot)
|
||||||
|
SETOSIndicationsAndReboot(EFI_OS_INDICATIONS_BOOT_TO_FW_UI);
|
||||||
|
else
|
||||||
|
RT->ResetSystem(EfiResetWarm, EFI_SUCCESS, 0, NULL);
|
||||||
|
--
|
||||||
|
2.7.4
|
||||||
|
|
||||||
@@ -0,0 +1,85 @@
|
|||||||
|
From 49b6a0bf2b9c69d1fd682fbc9d2ad7a7f6abee77 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Lans Zhang <jia.zhang@windriver.com>
|
||||||
|
Date: Fri, 22 Apr 2016 16:28:05 +0800
|
||||||
|
Subject: [PATCH] LockDown: enable the enrollment for DBX
|
||||||
|
|
||||||
|
Upstream-Status: Pending
|
||||||
|
|
||||||
|
DBX acting as blacklist now is able to be enrolled.
|
||||||
|
|
||||||
|
Signed-off-by: Lans Zhang <jia.zhang@windriver.com>
|
||||||
|
---
|
||||||
|
LockDown.c | 16 +++++++++++-----
|
||||||
|
Makefile | 4 +++-
|
||||||
|
2 files changed, 14 insertions(+), 6 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/LockDown.c b/LockDown.c
|
||||||
|
index 821985c..fec2e79 100644
|
||||||
|
--- a/LockDown.c
|
||||||
|
+++ b/LockDown.c
|
||||||
|
@@ -12,6 +12,7 @@
|
||||||
|
#include "PK.h"
|
||||||
|
#include "KEK.h"
|
||||||
|
#include "DB.h"
|
||||||
|
+#include "DBX.h"
|
||||||
|
|
||||||
|
EFI_STATUS
|
||||||
|
efi_main (EFI_HANDLE image, EFI_SYSTEM_TABLE *systab)
|
||||||
|
@@ -47,6 +48,7 @@ efi_main (EFI_HANDLE image, EFI_SYSTEM_TABLE *systab)
|
||||||
|
return efi_status;
|
||||||
|
}
|
||||||
|
Print(L"Created KEK Cert\n");
|
||||||
|
+
|
||||||
|
efi_status = RT->SetVariable(L"db", &SIG_DB,
|
||||||
|
EFI_VARIABLE_NON_VOLATILE
|
||||||
|
| EFI_VARIABLE_RUNTIME_ACCESS
|
||||||
|
@@ -58,15 +60,19 @@ efi_main (EFI_HANDLE image, EFI_SYSTEM_TABLE *systab)
|
||||||
|
return efi_status;
|
||||||
|
}
|
||||||
|
Print(L"Created db Cert\n");
|
||||||
|
-#if 0
|
||||||
|
- /* testing revocation ... this will revoke the certificate
|
||||||
|
- * we just enrolled in db */
|
||||||
|
- efi_status = SetSecureVariable(L"dbx", DB_cer, DB_cer_len, SIG_DB, 0);
|
||||||
|
+
|
||||||
|
+ efi_status = RT->SetVariable(L"dbx", &SIG_DB,
|
||||||
|
+ EFI_VARIABLE_NON_VOLATILE
|
||||||
|
+ | EFI_VARIABLE_RUNTIME_ACCESS
|
||||||
|
+ | EFI_VARIABLE_BOOTSERVICE_ACCESS
|
||||||
|
+ | EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS,
|
||||||
|
+ DBX_auth_len, DBX_auth);
|
||||||
|
if (efi_status != EFI_SUCCESS) {
|
||||||
|
Print(L"Failed to enroll dbx: %d\n", efi_status);
|
||||||
|
return efi_status;
|
||||||
|
}
|
||||||
|
-#endif
|
||||||
|
+ Print(L"Created dbx Cert\n");
|
||||||
|
+
|
||||||
|
/* PK must be updated with a signed copy of itself */
|
||||||
|
efi_status = RT->SetVariable(L"PK", &GV_GUID,
|
||||||
|
EFI_VARIABLE_NON_VOLATILE
|
||||||
|
diff --git a/Makefile b/Makefile
|
||||||
|
index b3bb73a..e189866 100644
|
||||||
|
--- a/Makefile
|
||||||
|
+++ b/Makefile
|
||||||
|
@@ -53,7 +53,7 @@ lib/asn1/libasn1.a lib/asn1/libasn1-efi.a: FORCE
|
||||||
|
.KEEP: PK.crt KEK.crt DB.crt PK.key KEK.key DB.key PK.esl DB.esl KEK.esl \
|
||||||
|
$(EFIFILES)
|
||||||
|
|
||||||
|
-LockDown.o: PK.h KEK.h DB.h
|
||||||
|
+LockDown.o: PK.h KEK.h DB.h DBX.h
|
||||||
|
PreLoader.o: hashlist.h
|
||||||
|
|
||||||
|
PK.h: PK.auth
|
||||||
|
@@ -62,6 +62,8 @@ KEK.h: KEK.auth
|
||||||
|
|
||||||
|
DB.h: DB.auth
|
||||||
|
|
||||||
|
+DBX.h: DBX.auth
|
||||||
|
+
|
||||||
|
noPK.esl:
|
||||||
|
> noPK.esl
|
||||||
|
|
||||||
|
--
|
||||||
|
1.9.1
|
||||||
|
|
||||||
@@ -0,0 +1,44 @@
|
|||||||
|
From b2897e78c7910f0e55f4861542155d2817c15bf4 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Lans Zhang <jia.zhang@windriver.com>
|
||||||
|
Date: Fri, 25 Mar 2016 10:52:34 +0800
|
||||||
|
Subject: [PATCH] LockDown: run system warm reset after the key provision
|
||||||
|
success
|
||||||
|
|
||||||
|
Upstream-Status: Pending
|
||||||
|
|
||||||
|
In addition, BIOS would stop at its setup screen. The end user can thus
|
||||||
|
enable UEFI secure boot immediately.
|
||||||
|
|
||||||
|
Signed-off-by: Lans Zhang <jia.zhang@windriver.com>
|
||||||
|
---
|
||||||
|
LockDown.c | 15 +++++++++++++++
|
||||||
|
1 file changed, 15 insertions(+)
|
||||||
|
|
||||||
|
diff --git a/LockDown.c b/LockDown.c
|
||||||
|
index 29df9de..821985c 100644
|
||||||
|
--- a/LockDown.c
|
||||||
|
+++ b/LockDown.c
|
||||||
|
@@ -99,5 +99,20 @@ efi_main (EFI_HANDLE image, EFI_SYSTEM_TABLE *systab)
|
||||||
|
}
|
||||||
|
Print(L"Platform %s set to boot securely\n", SecureBoot ? L"is" : L"is not");
|
||||||
|
|
||||||
|
+ /* Reset system to go back the real UEFI secure boot flow.
|
||||||
|
+ * If SecureBoot is still false, the user needs to turn on
|
||||||
|
+ * UEFI secure boot in BIOS setup.
|
||||||
|
+ */
|
||||||
|
+ Print(L"Prepare to execute system warm reset after 3 seconds ...\n");
|
||||||
|
+ if (!SecureBoot)
|
||||||
|
+ Print(L"After warm reset, enter to BIOS setup to enable UEFI Secure Boot.\n");
|
||||||
|
+
|
||||||
|
+ BS->Stall(3000000);
|
||||||
|
+
|
||||||
|
+ if (!SecureBoot)
|
||||||
|
+ SETOSIndicationsAndReboot(EFI_OS_INDICATIONS_BOOT_TO_FW_UI);
|
||||||
|
+ else
|
||||||
|
+ RT->ResetSystem(EfiResetWarm, EFI_SUCCESS, 0, NULL);
|
||||||
|
+
|
||||||
|
return EFI_SUCCESS;
|
||||||
|
}
|
||||||
|
--
|
||||||
|
1.9.1
|
||||||
|
|
||||||
@@ -0,0 +1,94 @@
|
|||||||
|
From 28eb6a3118c3c843b41732ec3cf5167fe027daba Mon Sep 17 00:00:00 2001
|
||||||
|
From: Lans Zhang <jia.zhang@windriver.com>
|
||||||
|
Date: Tue, 17 Jan 2017 12:48:27 +0800
|
||||||
|
Subject: [PATCH] LockDown: show the error message with 3-sec timeout
|
||||||
|
|
||||||
|
Signed-off-by: Lans Zhang <jia.zhang@windriver.com>
|
||||||
|
---
|
||||||
|
LockDown.c | 20 ++++++++++++--------
|
||||||
|
1 file changed, 12 insertions(+), 8 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/LockDown.c b/LockDown.c
|
||||||
|
index fec2e79..13c626f 100644
|
||||||
|
--- a/LockDown.c
|
||||||
|
+++ b/LockDown.c
|
||||||
|
@@ -27,12 +27,12 @@ efi_main (EFI_HANDLE image, EFI_SYSTEM_TABLE *systab)
|
||||||
|
|
||||||
|
if (efi_status != EFI_SUCCESS) {
|
||||||
|
Print(L"No SetupMode variable ... is platform secure boot enabled?\n");
|
||||||
|
- return EFI_SUCCESS;
|
||||||
|
+ goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!SetupMode) {
|
||||||
|
Print(L"Platform is not in Setup Mode, cannot install Keys\n");
|
||||||
|
- return EFI_SUCCESS;
|
||||||
|
+ goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
Print(L"Platform is in Setup Mode\n");
|
||||||
|
@@ -45,7 +45,7 @@ efi_main (EFI_HANDLE image, EFI_SYSTEM_TABLE *systab)
|
||||||
|
KEK_auth_len, KEK_auth);
|
||||||
|
if (efi_status != EFI_SUCCESS) {
|
||||||
|
Print(L"Failed to enroll KEK: %d\n", efi_status);
|
||||||
|
- return efi_status;
|
||||||
|
+ goto out;
|
||||||
|
}
|
||||||
|
Print(L"Created KEK Cert\n");
|
||||||
|
|
||||||
|
@@ -57,7 +57,7 @@ efi_main (EFI_HANDLE image, EFI_SYSTEM_TABLE *systab)
|
||||||
|
DB_auth_len, DB_auth);
|
||||||
|
if (efi_status != EFI_SUCCESS) {
|
||||||
|
Print(L"Failed to enroll db: %d\n", efi_status);
|
||||||
|
- return efi_status;
|
||||||
|
+ goto out;
|
||||||
|
}
|
||||||
|
Print(L"Created db Cert\n");
|
||||||
|
|
||||||
|
@@ -69,7 +69,7 @@ efi_main (EFI_HANDLE image, EFI_SYSTEM_TABLE *systab)
|
||||||
|
DBX_auth_len, DBX_auth);
|
||||||
|
if (efi_status != EFI_SUCCESS) {
|
||||||
|
Print(L"Failed to enroll dbx: %d\n", efi_status);
|
||||||
|
- return efi_status;
|
||||||
|
+ goto out;
|
||||||
|
}
|
||||||
|
Print(L"Created dbx Cert\n");
|
||||||
|
|
||||||
|
@@ -84,14 +84,14 @@ efi_main (EFI_HANDLE image, EFI_SYSTEM_TABLE *systab)
|
||||||
|
|
||||||
|
if (efi_status != EFI_SUCCESS) {
|
||||||
|
Print(L"Failed to enroll PK: %d\n", efi_status);
|
||||||
|
- return efi_status;
|
||||||
|
+ goto out;
|
||||||
|
}
|
||||||
|
Print(L"Created PK Cert\n");
|
||||||
|
/* enrolling the PK should put us in SetupMode; check this */
|
||||||
|
efi_status = RT->GetVariable(L"SetupMode", &GV_GUID, NULL, &DataSize, &SetupMode);
|
||||||
|
if (efi_status != EFI_SUCCESS) {
|
||||||
|
Print(L"Failed to get SetupMode variable: %d\n", efi_status);
|
||||||
|
- return efi_status;
|
||||||
|
+ goto out;
|
||||||
|
}
|
||||||
|
Print(L"Platform is in %s Mode\n", SetupMode ? L"Setup" : L"User");
|
||||||
|
|
||||||
|
@@ -101,7 +101,7 @@ efi_main (EFI_HANDLE image, EFI_SYSTEM_TABLE *systab)
|
||||||
|
|
||||||
|
if (efi_status != EFI_SUCCESS) {
|
||||||
|
Print(L"Failed to get SecureBoot variable: %d\n", efi_status);
|
||||||
|
- return efi_status;
|
||||||
|
+ goto out;
|
||||||
|
}
|
||||||
|
Print(L"Platform %s set to boot securely\n", SecureBoot ? L"is" : L"is not");
|
||||||
|
|
||||||
|
@@ -121,4 +121,8 @@ efi_main (EFI_HANDLE image, EFI_SYSTEM_TABLE *systab)
|
||||||
|
RT->ResetSystem(EfiResetWarm, EFI_SUCCESS, 0, NULL);
|
||||||
|
|
||||||
|
return EFI_SUCCESS;
|
||||||
|
+
|
||||||
|
+out:
|
||||||
|
+ BS->Stall(3000000);
|
||||||
|
+ return efi_status;
|
||||||
|
}
|
||||||
|
--
|
||||||
|
2.7.4
|
||||||
|
|
||||||
@@ -0,0 +1,33 @@
|
|||||||
|
From 923b9cb2bfe81ff29a29d46bfc4e3fe172e0e5ae Mon Sep 17 00:00:00 2001
|
||||||
|
From: Yunguo Wei <yunguo.wei@windriver.com>
|
||||||
|
Date: Tue, 17 Jan 2017 17:24:51 +0800
|
||||||
|
Subject: [PATCH] Makefile: do not build signed efi image
|
||||||
|
|
||||||
|
Signed-off-by: Yunguo Wei <yunguo.wei@windriver.com>
|
||||||
|
---
|
||||||
|
Makefile | 5 ++---
|
||||||
|
1 file changed, 2 insertions(+), 3 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/Makefile b/Makefile
|
||||||
|
index addb593..a1fc538 100644
|
||||||
|
--- a/Makefile
|
||||||
|
+++ b/Makefile
|
||||||
|
@@ -1,5 +1,4 @@
|
||||||
|
-EFIFILES = HelloWorld.efi LockDown.efi Loader.efi ReadVars.efi UpdateVars.efi \
|
||||||
|
- KeyTool.efi HashTool.efi SetNull.efi ShimReplace.efi
|
||||||
|
+EFIFILES = LockDown.efi
|
||||||
|
BINARIES = cert-to-efi-sig-list sig-list-to-certs sign-efi-sig-list \
|
||||||
|
hash-to-efi-sig-list efi-readvar efi-updatevar cert-to-efi-hash-list \
|
||||||
|
flash-var
|
||||||
|
@@ -27,7 +26,7 @@ include Make.rules
|
||||||
|
|
||||||
|
EFISIGNED = $(patsubst %.efi,%-signed.efi,$(EFIFILES))
|
||||||
|
|
||||||
|
-all: $(EFISIGNED) $(BINARIES) $(MANPAGES) noPK.auth $(KEYAUTH) \
|
||||||
|
+all: $(EFIFILES) $(BINARIES) $(MANPAGES) noPK.auth $(KEYAUTH) \
|
||||||
|
$(KEYUPDATEAUTH) $(KEYBLACKLISTAUTH) $(KEYHASHBLACKLISTAUTH)
|
||||||
|
|
||||||
|
|
||||||
|
--
|
||||||
|
2.7.4
|
||||||
|
|
||||||
@@ -0,0 +1,51 @@
|
|||||||
|
From 959e4395b5524babb27c2bf95fa37b990d79b663 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Lans Zhang <jia.zhang@windriver.com>
|
||||||
|
Date: Thu, 28 Apr 2016 12:52:22 +0800
|
||||||
|
Subject: [PATCH] Reuse xxdi.pl
|
||||||
|
|
||||||
|
The missing File::Slurp required by xxdi.pl is added. To avoid introducing
|
||||||
|
an extra xxd package, remove the support of using xxd.
|
||||||
|
|
||||||
|
Signed-off-by: Lans Zhang <jia.zhang@windriver.com>
|
||||||
|
---
|
||||||
|
Make.rules | 3 +--
|
||||||
|
Makefile | 2 +-
|
||||||
|
2 files changed, 2 insertions(+), 3 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/Make.rules b/Make.rules
|
||||||
|
index 21926b0..38c7a22 100644
|
||||||
|
--- a/Make.rules
|
||||||
|
+++ b/Make.rules
|
||||||
|
@@ -33,7 +33,6 @@ NM = nm
|
||||||
|
AR = ar
|
||||||
|
OPENSSL = openssl
|
||||||
|
SBSIGN = sbsign
|
||||||
|
-XXD = xxd
|
||||||
|
SIGN_EFI_SIG_LIST ?= ./sign-efi-sig-list
|
||||||
|
CERT_TO_EFI_SIG_LIST ?= ./cert-to-efi-sig-list
|
||||||
|
CERT_TO_EFI_HASH_LIST ?= ./cert-to-efi-hash-list
|
||||||
|
@@ -76,7 +75,7 @@ endif
|
||||||
|
${NM} -D $@ | grep ' U ' && exit 1 || exit 0
|
||||||
|
|
||||||
|
%.h: %.auth
|
||||||
|
- $(XXD) -i $< > $@
|
||||||
|
+ ./xxdi.pl $< > $@
|
||||||
|
|
||||||
|
%.hash: %.efi hash-to-efi-sig-list
|
||||||
|
$(HASH_TO_EFI_SIG_LIST) $< $@
|
||||||
|
diff --git a/Makefile b/Makefile
|
||||||
|
index da363a6..2534b47 100644
|
||||||
|
--- a/Makefile
|
||||||
|
+++ b/Makefile
|
||||||
|
@@ -73,7 +73,7 @@ ms-%.esl: ms-%.crt cert-to-efi-sig-list
|
||||||
|
|
||||||
|
hashlist.h: HashTool.hash
|
||||||
|
cat $^ > /tmp/tmp.hash
|
||||||
|
- $(XXD) -i /tmp/tmp.hash > $@
|
||||||
|
+ ./xxdi.pl /tmp/tmp.hash > $@
|
||||||
|
rm -f /tmp/tmp.hash
|
||||||
|
|
||||||
|
|
||||||
|
--
|
||||||
|
1.9.1
|
||||||
|
|
||||||
83
meta-efi-secure-boot/recipes-bsp/efitools/efitools_git.bb
Normal file
83
meta-efi-secure-boot/recipes-bsp/efitools/efitools_git.bb
Normal file
@@ -0,0 +1,83 @@
|
|||||||
|
require efitools.inc
|
||||||
|
|
||||||
|
SRC_URI_append += " \
|
||||||
|
file://LockDown-enable-the-enrollment-for-DBX.patch \
|
||||||
|
file://LockDown-show-the-error-message-with-3-sec-timeout.patch \
|
||||||
|
file://Makefile-do-not-build-signed-efi-image.patch \
|
||||||
|
file://Build-DBX-by-default.patch \
|
||||||
|
file://LockDown-disable-the-entrance-into-BIOS-setup-to-re-.patch \
|
||||||
|
file://Fix-help2man-error.patch \
|
||||||
|
"
|
||||||
|
|
||||||
|
COMPATIBLE_HOST = '(i.86|x86_64).*-linux'
|
||||||
|
|
||||||
|
inherit user-key-store deploy
|
||||||
|
|
||||||
|
# The generated native binaries are used during native and target build
|
||||||
|
DEPENDS += "${BPN}-native gnu-efi openssl"
|
||||||
|
|
||||||
|
RDEPENDS_${PN}_append += " \
|
||||||
|
parted mtools coreutils util-linux openssl libcrypto \
|
||||||
|
"
|
||||||
|
|
||||||
|
EXTRA_OEMAKE_append += " \
|
||||||
|
INCDIR_PREFIX='${STAGING_DIR_TARGET}' \
|
||||||
|
CRTPATH_PREFIX='${STAGING_DIR_TARGET}' \
|
||||||
|
SIGN_EFI_SIG_LIST='${STAGING_BINDIR_NATIVE}/sign-efi-sig-list' \
|
||||||
|
CERT_TO_EFI_SIG_LIST='${STAGING_BINDIR_NATIVE}/cert-to-efi-sig-list' \
|
||||||
|
CERT_TO_EFI_HASH_LIST='${STAGING_BINDIR_NATIVE}/cert-to-efi-hash-list' \
|
||||||
|
HASH_TO_EFI_SIG_LIST='${STAGING_BINDIR_NATIVE}/hash-to-efi-sig-list' \
|
||||||
|
MYGUID='${UEFI_SIG_OWNER_GUID}' \
|
||||||
|
HELP2MAN_PROG_PREFIX='${STAGING_BINDIR_NATIVE}' \
|
||||||
|
"
|
||||||
|
|
||||||
|
python do_prepare_signing_keys() {
|
||||||
|
if d.expand('${UEFI_SB}') != '1':
|
||||||
|
return
|
||||||
|
|
||||||
|
# Prepare PK, KEK and DB for LockDown.efi.
|
||||||
|
if uks_signing_model(d) in ('sample', 'user'):
|
||||||
|
dir = uefi_sb_keys_dir(d)
|
||||||
|
else:
|
||||||
|
dir = d.expand('${SAMPLE_UEFI_SB_KEYS_DIR}/')
|
||||||
|
|
||||||
|
import shutil
|
||||||
|
|
||||||
|
for _ in ('PK', 'KEK', 'DB'):
|
||||||
|
shutil.copyfile(dir + _ + '.pem', d.expand('${S}/') + _ + '.crt')
|
||||||
|
shutil.copyfile(dir + _ + '.key', d.expand('${S}/') + _ + '.key')
|
||||||
|
|
||||||
|
# Make sure LockDown.efi contains the DB and KEK from Microsoft.
|
||||||
|
if "${@bb.utils.contains('DISTRO_FEATURES', 'msft', '1', '0', d)}" == '1':
|
||||||
|
shutil.copyfile(d.expand('${MSFT_DB_CERT}'), d.expand('${S}/DB.crt'))
|
||||||
|
shutil.copyfile(d.expand('${MSFT_KEK_CERT}'), d.expand('${S}/KEK.crt'))
|
||||||
|
|
||||||
|
path = create_uefi_dbx(d)
|
||||||
|
if path:
|
||||||
|
with open(d.expand('${S}/DBX.crt'), 'w') as f:
|
||||||
|
pass
|
||||||
|
|
||||||
|
shutil.copyfile(path, d.expand('${S}/DBX.esl'))
|
||||||
|
|
||||||
|
# Cheat the Makefile to avoid running this rule:
|
||||||
|
# %.esl: %.crt cert-to-efi-sig-list
|
||||||
|
# $(CERT_TO_EFI_SIG_LIST) -g $(MYGUID) $< $@
|
||||||
|
import time, os
|
||||||
|
tm = time.strptime('2038-01-01 00:00:00', \
|
||||||
|
'%Y-%m-%d %H:%M:%S')
|
||||||
|
time_stamp = time.mktime(tm)
|
||||||
|
os.utime(d.expand('${S}/DBX.esl'), (time_stamp, time_stamp))
|
||||||
|
}
|
||||||
|
addtask prepare_signing_keys after do_configure before do_compile
|
||||||
|
|
||||||
|
do_install_append() {
|
||||||
|
install -d ${D}${EFI_BOOT_PATH}
|
||||||
|
install -m 0755 ${D}${datadir}/efitools/efi/LockDown.efi ${D}${EFI_BOOT_PATH}
|
||||||
|
}
|
||||||
|
|
||||||
|
do_deploy() {
|
||||||
|
install -d ${DEPLOYDIR}
|
||||||
|
|
||||||
|
install -m 0600 ${D}${EFI_BOOT_PATH}/LockDown.efi "${DEPLOYDIR}"
|
||||||
|
}
|
||||||
|
addtask deploy after do_install before do_build
|
||||||
@@ -0,0 +1,67 @@
|
|||||||
|
From aecadf65c4d3dea68e55605ff5f0c3eb90206488 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Ricardo Neri <ricardo.neri-calderon@linux.intel.com>
|
||||||
|
Date: Fri, 27 Mar 2015 08:01:41 -0700
|
||||||
|
Subject: [PATCH 1/7] pe32.h: add header structures for TE and DOS executables
|
||||||
|
|
||||||
|
Upstream-Status: Inappropriate [embedded specific]
|
||||||
|
|
||||||
|
Add header structures to describe the Terse Executable format and
|
||||||
|
the DOS header format for executable images.
|
||||||
|
|
||||||
|
These definitions are needed in subsequent commits to parse and
|
||||||
|
verify the identity of the executable image when utilizing a shim
|
||||||
|
to boot LUV.
|
||||||
|
|
||||||
|
Signed-off-by: Ricardo Neri <ricardo.neri-calderon@linux.intel.com>
|
||||||
|
---
|
||||||
|
include/grub/efi/pe32.h | 36 ++++++++++++++++++++++++++++++++++++
|
||||||
|
1 file changed, 36 insertions(+)
|
||||||
|
|
||||||
|
diff --git a/include/grub/efi/pe32.h b/include/grub/efi/pe32.h
|
||||||
|
index c3efa9b..c1c3483 100644
|
||||||
|
--- a/include/grub/efi/pe32.h
|
||||||
|
+++ b/include/grub/efi/pe32.h
|
||||||
|
@@ -313,4 +313,40 @@ struct grub_pe32_reloc
|
||||||
|
#define GRUB_PE32_REL_I386_DIR32 0x6
|
||||||
|
#define GRUB_PE32_REL_I386_REL32 0x14
|
||||||
|
|
||||||
|
+struct grub_te_header
|
||||||
|
+{
|
||||||
|
+ grub_uint16_t signature;
|
||||||
|
+ grub_uint16_t machine;
|
||||||
|
+ grub_uint8_t num_sections;
|
||||||
|
+ grub_uint8_t subsystem;
|
||||||
|
+ grub_uint16_t stripped_size;
|
||||||
|
+ grub_uint32_t entry_point;
|
||||||
|
+ grub_uint32_t code_base;
|
||||||
|
+ grub_uint64_t image_base;
|
||||||
|
+ struct grub_pe32_data_directory data_directory[2];
|
||||||
|
+};
|
||||||
|
+
|
||||||
|
+struct grub_dos_header
|
||||||
|
+{
|
||||||
|
+ grub_uint16_t magic;
|
||||||
|
+ grub_uint16_t cblp;
|
||||||
|
+ grub_uint16_t cp;
|
||||||
|
+ grub_uint16_t crlc;
|
||||||
|
+ grub_uint16_t cparhdr;
|
||||||
|
+ grub_uint16_t minalloc;
|
||||||
|
+ grub_uint16_t maxalloc;
|
||||||
|
+ grub_uint16_t ss;
|
||||||
|
+ grub_uint16_t sp;
|
||||||
|
+ grub_uint16_t csum;
|
||||||
|
+ grub_uint16_t ip;
|
||||||
|
+ grub_uint16_t cs;
|
||||||
|
+ grub_uint16_t lfarlc;
|
||||||
|
+ grub_uint16_t ovno;
|
||||||
|
+ grub_uint16_t res[4];
|
||||||
|
+ grub_uint16_t oemid;
|
||||||
|
+ grub_uint16_t oeminfo;
|
||||||
|
+ grub_uint16_t res2[10];
|
||||||
|
+ grub_uint32_t lfanew;
|
||||||
|
+};
|
||||||
|
+
|
||||||
|
#endif /* ! GRUB_EFI_PE32_HEADER */
|
||||||
|
--
|
||||||
|
1.9.1
|
||||||
|
|
||||||
@@ -0,0 +1,161 @@
|
|||||||
|
From 2341c2d2cf2ee67b036d21aa9b12b71bea84495f Mon Sep 17 00:00:00 2001
|
||||||
|
From: Ricardo Neri <ricardo.neri-calderon@linux.intel.com>
|
||||||
|
Date: Fri, 27 Mar 2015 08:09:58 -0700
|
||||||
|
Subject: [PATCH 2/7] shim: add needed data structures
|
||||||
|
|
||||||
|
Upstream-Status: Inappropriate [embedded specific]
|
||||||
|
|
||||||
|
Add the needed data structures for shim to load, parse, relocate and
|
||||||
|
execute a binary. This includes file-parsing structures, an identifier for
|
||||||
|
the UEFI protocol for image verification under secure boot provided by shim.
|
||||||
|
|
||||||
|
Shim is thin loader developed by Matthew Garret
|
||||||
|
(https://github.com/rhinstaller/shim). This code was ported from such project.
|
||||||
|
|
||||||
|
Signed-off-by: Ricardo Neri <ricardo.neri-calderon@linux.intel.com>
|
||||||
|
---
|
||||||
|
include/grub/efi/shim.h | 132 ++++++++++++++++++++++++++++++++++++++++++++++++
|
||||||
|
1 file changed, 132 insertions(+)
|
||||||
|
create mode 100644 include/grub/efi/shim.h
|
||||||
|
|
||||||
|
diff --git a/include/grub/efi/shim.h b/include/grub/efi/shim.h
|
||||||
|
new file mode 100644
|
||||||
|
index 0000000..4b92a00
|
||||||
|
--- /dev/null
|
||||||
|
+++ b/include/grub/efi/shim.h
|
||||||
|
@@ -0,0 +1,132 @@
|
||||||
|
+/*
|
||||||
|
+ * shim.h - interface to shim: UEFI first-stage bootloader
|
||||||
|
+ *
|
||||||
|
+ * Copyright 2015 Intel Corporation.
|
||||||
|
+ *
|
||||||
|
+ * Redistribution and use in source and binary forms, with or without
|
||||||
|
+ * modification, are permitted provided that the following conditions
|
||||||
|
+ * are met:
|
||||||
|
+ *
|
||||||
|
+ * Redistributions of source code must retain the above copyright
|
||||||
|
+ * notice, this list of conditions and the following disclaimer.
|
||||||
|
+ *
|
||||||
|
+ * Redistributions in binary form must reproduce the above copyright
|
||||||
|
+ * notice, this list of conditions and the following disclaimer in the
|
||||||
|
+ * documentation and/or other materials provided with the
|
||||||
|
+ * distribution.
|
||||||
|
+ *
|
||||||
|
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||||
|
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||||
|
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||||
|
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||||
|
+ * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
|
||||||
|
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||||
|
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||||
|
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||||
|
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
||||||
|
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||||
|
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
|
||||||
|
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
+ *
|
||||||
|
+ * Significant portions of this code are derived from Red Hat shim: UEFI
|
||||||
|
+ * first-stage bootloader.
|
||||||
|
+ * (https://github.com/rhinstaller/shim) and are Copyright 2012 Red Hat, Inc
|
||||||
|
+ */
|
||||||
|
+
|
||||||
|
+#ifndef GRUB_SHIM_HEADER
|
||||||
|
+#define GRUB_SHIM_HEADER 1
|
||||||
|
+
|
||||||
|
+#include <grub/efi/pe32.h>
|
||||||
|
+
|
||||||
|
+struct grub_nt_headers32
|
||||||
|
+{
|
||||||
|
+ grub_efi_uint32_t signature;
|
||||||
|
+ struct grub_pe32_coff_header file_hdr;
|
||||||
|
+ struct grub_pe32_optional_header opt_hdr;
|
||||||
|
+};
|
||||||
|
+
|
||||||
|
+struct grub_nt_headers64
|
||||||
|
+{
|
||||||
|
+ grub_efi_uint32_t signature;
|
||||||
|
+ struct grub_pe32_coff_header file_hdr;
|
||||||
|
+ struct grub_pe64_optional_header opt_hdr;
|
||||||
|
+};
|
||||||
|
+
|
||||||
|
+struct grub_image_base_relocation
|
||||||
|
+{
|
||||||
|
+ grub_efi_uint32_t virtual_address;
|
||||||
|
+ grub_efi_uint32_t block_size;
|
||||||
|
+};
|
||||||
|
+
|
||||||
|
+struct grub_shim_pe_coff_loader_image_context {
|
||||||
|
+ grub_efi_uint64_t image_address;
|
||||||
|
+ grub_efi_uint64_t image_size;
|
||||||
|
+ grub_efi_uint64_t entry_point;
|
||||||
|
+ grub_efi_uintn_t header_size;
|
||||||
|
+ grub_efi_uint16_t image_type;
|
||||||
|
+ grub_efi_uint16_t num_sections;
|
||||||
|
+ struct grub_pe32_section_table *first_section;
|
||||||
|
+ struct grub_pe32_data_directory *reloc_dir;
|
||||||
|
+ struct grub_pe32_data_directory *sec_dir;
|
||||||
|
+ grub_efi_uint64_t number_of_rva_and_sizes;
|
||||||
|
+ union grub_shim_optional_header_union *pe_hdr;
|
||||||
|
+};
|
||||||
|
+
|
||||||
|
+struct grub_shim_lock
|
||||||
|
+{
|
||||||
|
+ grub_efi_status_t
|
||||||
|
+ (*verify) (void *buffer,
|
||||||
|
+ grub_uint32_t size);
|
||||||
|
+
|
||||||
|
+ grub_efi_status_t
|
||||||
|
+ (*hash) (grub_int8_t *data,
|
||||||
|
+ grub_int32_t datasize,
|
||||||
|
+ struct grub_shim_pe_coff_loader_image_context *context,
|
||||||
|
+ grub_uint8_t sha256hash,
|
||||||
|
+ grub_uint8_t sha1hash);
|
||||||
|
+
|
||||||
|
+ grub_efi_status_t
|
||||||
|
+ (*context) (void *data,
|
||||||
|
+ grub_uint32_t datasize,
|
||||||
|
+ struct grub_shim_pe_coff_loader_image_context *context);
|
||||||
|
+};
|
||||||
|
+
|
||||||
|
+union grub_shim_optional_header_union
|
||||||
|
+{
|
||||||
|
+ struct grub_nt_headers32 pe32;
|
||||||
|
+ struct grub_nt_headers64 pe32plus;
|
||||||
|
+ struct grub_te_header te;
|
||||||
|
+};
|
||||||
|
+
|
||||||
|
+#define GRUB_EFI_SHIM_PROTOCOL_GUID \
|
||||||
|
+ { 0x605dab50, 0xe046, 0x4300, \
|
||||||
|
+ { 0xab, 0xb6, 0x3d, 0xd8, 0x10, 0xdd, 0x8b, 0x23 } \
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+#define SIGNATURE_16(A, B) ((A) | (B << 8))
|
||||||
|
+#define SIGNATURE_32(A, B, C, D) (SIGNATURE_16 (A, B) | (SIGNATURE_16 (C, D) << 16))
|
||||||
|
+
|
||||||
|
+#define EFI_IMAGE_DOS_SIGNATURE SIGNATURE_16('M', 'Z')
|
||||||
|
+#define EFI_IMAGE_NT_SIGNATURE SIGNATURE_32('P', 'E', '\0', '\0')
|
||||||
|
+
|
||||||
|
+#define EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC 5
|
||||||
|
+
|
||||||
|
+#define ALIGN_VALUE(Value, Alignment) ((Value) + (((Alignment) - (Value)) & ((Alignment) - 1)))
|
||||||
|
+#define ALIGN_POINTER(Pointer, Alignment) ((void *) (ALIGN_VALUE ((grub_efi_uintn_t)(Pointer), (Alignment))))
|
||||||
|
+
|
||||||
|
+/* Based relocation types. */
|
||||||
|
+
|
||||||
|
+#define EFI_IMAGE_REL_BASED_ABSOLUTE 0
|
||||||
|
+#define EFI_IMAGE_REL_BASED_HIGH 1
|
||||||
|
+#define EFI_IMAGE_REL_BASED_LOW 2
|
||||||
|
+#define EFI_IMAGE_REL_BASED_HIGHLOW 3
|
||||||
|
+#define EFI_IMAGE_REL_BASED_HIGHADJ 4
|
||||||
|
+#define EFI_IMAGE_REL_BASED_MIPS_JMPADDR 5
|
||||||
|
+#define EFI_IMAGE_REL_BASED_ARM_MOV32A 5
|
||||||
|
+#define EFI_IMAGE_REL_BASED_ARM_MOV32T 7
|
||||||
|
+#define EFI_IMAGE_REL_BASED_IA64_IMM64 9
|
||||||
|
+#define EFI_IMAGE_REL_BASED_MIPS_JMPADDR16 9
|
||||||
|
+#define EFI_IMAGE_REL_BASED_DIR64 10
|
||||||
|
+
|
||||||
|
+
|
||||||
|
+#endif /* ! GRUB_SHIM_HEADER */
|
||||||
|
--
|
||||||
|
1.9.1
|
||||||
|
|
||||||
@@ -0,0 +1,81 @@
|
|||||||
|
From 3b75fa5071e4b1a40510669119791928859b46e7 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Matt Fleming <matt.fleming@intel.com>
|
||||||
|
Date: Fri, 27 Mar 2015 08:11:19 -0700
|
||||||
|
Subject: [PATCH 3/7] efi: chainloader: implement an UEFI Exit service for shim
|
||||||
|
in grub
|
||||||
|
|
||||||
|
Upstream-Status: Inappropriate [embedded specific]
|
||||||
|
|
||||||
|
When exiting, grub will call the UEFI boot-time service Exit. The
|
||||||
|
effect of this is that UEFI will jump to the entry point of the
|
||||||
|
UEFI started image. If we execute an image using shim within grub,
|
||||||
|
shim takes care of loading/parsing/relocating/executing the image.
|
||||||
|
Under this scenario, we also need to take care of the Exit call. Thus,
|
||||||
|
we need to reimplement the function to make sure we perform a jump
|
||||||
|
to the instruction after which shim executed the image.
|
||||||
|
|
||||||
|
Once we have taken care of the exit of the shim-executed image
|
||||||
|
the system Exit call is restored.
|
||||||
|
|
||||||
|
Signed-off-by: Ricardo Neri <ricardo.neri-calderon@linux.intel.com>
|
||||||
|
---
|
||||||
|
grub-core/kern/x86_64/efi/callwrap.S | 23 +++++++++++++++++++++++
|
||||||
|
include/grub/efi/api.h | 4 ++++
|
||||||
|
2 files changed, 27 insertions(+)
|
||||||
|
|
||||||
|
diff --git a/grub-core/kern/x86_64/efi/callwrap.S b/grub-core/kern/x86_64/efi/callwrap.S
|
||||||
|
index 2df95dd..f0f1dd8 100644
|
||||||
|
--- a/grub-core/kern/x86_64/efi/callwrap.S
|
||||||
|
+++ b/grub-core/kern/x86_64/efi/callwrap.S
|
||||||
|
@@ -48,6 +48,26 @@ FUNCTION(efi_wrap_1)
|
||||||
|
addq $48, %rsp
|
||||||
|
ret
|
||||||
|
|
||||||
|
+FUNCTION(efi_call_foo)
|
||||||
|
+ pushq %rbp
|
||||||
|
+ pushq %r12
|
||||||
|
+ pushq %r13
|
||||||
|
+ pushq %r14
|
||||||
|
+ pushq %r15
|
||||||
|
+ movq %rsp, saved_sp(%rip)
|
||||||
|
+ subq $48, %rsp
|
||||||
|
+ mov %rsi, %rcx
|
||||||
|
+ call *%rdi
|
||||||
|
+
|
||||||
|
+FUNCTION(efi_shim_exit)
|
||||||
|
+ movq saved_sp(%rip), %rsp
|
||||||
|
+ popq %r15
|
||||||
|
+ popq %r14
|
||||||
|
+ popq %r13
|
||||||
|
+ popq %r12
|
||||||
|
+ popq %rbp
|
||||||
|
+ ret
|
||||||
|
+
|
||||||
|
FUNCTION(efi_wrap_2)
|
||||||
|
subq $48, %rsp
|
||||||
|
mov %rsi, %rcx
|
||||||
|
@@ -127,3 +147,6 @@ FUNCTION(efi_wrap_10)
|
||||||
|
call *%rdi
|
||||||
|
addq $96, %rsp
|
||||||
|
ret
|
||||||
|
+
|
||||||
|
+ .data
|
||||||
|
+saved_sp: .quad 0
|
||||||
|
diff --git a/include/grub/efi/api.h b/include/grub/efi/api.h
|
||||||
|
index 26127de..374d88b 100644
|
||||||
|
--- a/include/grub/efi/api.h
|
||||||
|
+++ b/include/grub/efi/api.h
|
||||||
|
@@ -1437,6 +1437,10 @@ typedef struct grub_efi_block_io grub_efi_block_io_t;
|
||||||
|
|
||||||
|
grub_uint64_t EXPORT_FUNC(efi_wrap_0) (void *func);
|
||||||
|
grub_uint64_t EXPORT_FUNC(efi_wrap_1) (void *func, grub_uint64_t arg1);
|
||||||
|
+grub_efi_status_t EXPORT_FUNC(efi_shim_exit) (grub_efi_handle_t handle, grub_efi_status_t exit_status,
|
||||||
|
+ grub_efi_uintn_t exit_data_size, grub_efi_char16_t *exit_data) __attribute__((noreturn));
|
||||||
|
+grub_uint64_t EXPORT_FUNC(efi_call_foo) (void *func, grub_uint64_t arg1,
|
||||||
|
+ grub_uint64_t arg2);
|
||||||
|
grub_uint64_t EXPORT_FUNC(efi_wrap_2) (void *func, grub_uint64_t arg1,
|
||||||
|
grub_uint64_t arg2);
|
||||||
|
grub_uint64_t EXPORT_FUNC(efi_wrap_3) (void *func, grub_uint64_t arg1,
|
||||||
|
--
|
||||||
|
1.9.1
|
||||||
|
|
||||||
@@ -0,0 +1,582 @@
|
|||||||
|
From e097b4e25469aabdceac79c45cca27029824c1b5 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Ricardo Neri <ricardo.neri-calderon@linux.intel.com>
|
||||||
|
Date: Fri, 27 Mar 2015 08:19:21 -0700
|
||||||
|
Subject: [PATCH 4/7] efi: chainloader: port shim to grub
|
||||||
|
|
||||||
|
Upstream-Status: Inappropriate [embedded specific]
|
||||||
|
|
||||||
|
Shim is a thin loader to execute signed binaries under the
|
||||||
|
chain of trust of UEFI secure boot. Before executing the image,
|
||||||
|
shim verifies that such image is signed with any of the Machine
|
||||||
|
Owner Keys (MOKs). If the verification is successful, shim will
|
||||||
|
load, parse, relocate and execute the image.
|
||||||
|
|
||||||
|
Shim is useful in case the user does not want to modify the UEFI
|
||||||
|
database of valid certificates (DB).
|
||||||
|
|
||||||
|
This commit ports Matthew Garret's code from shim to grub in order
|
||||||
|
to provide to grub the capability of load and execute trusted
|
||||||
|
binaries. This is useful in case we need to chainload two bootloaders.
|
||||||
|
|
||||||
|
Shim can be found here: https://github.com/rhinstaller/shim
|
||||||
|
|
||||||
|
Signed-off-by: Ricardo Neri <ricardo.neri-calderon@linux.intel.com>
|
||||||
|
---
|
||||||
|
grub-core/loader/efi/chainloader.c | 534 +++++++++++++++++++++++++++++++++++++
|
||||||
|
1 file changed, 534 insertions(+)
|
||||||
|
|
||||||
|
diff --git a/grub-core/loader/efi/chainloader.c b/grub-core/loader/efi/chainloader.c
|
||||||
|
index 3f3e6e3..bd83859 100644
|
||||||
|
--- a/grub-core/loader/efi/chainloader.c
|
||||||
|
+++ b/grub-core/loader/efi/chainloader.c
|
||||||
|
@@ -32,6 +32,7 @@
|
||||||
|
#include <grub/efi/api.h>
|
||||||
|
#include <grub/efi/efi.h>
|
||||||
|
#include <grub/efi/disk.h>
|
||||||
|
+#include <grub/efi/shim.h>
|
||||||
|
#include <grub/command.h>
|
||||||
|
#include <grub/i18n.h>
|
||||||
|
#include <grub/net.h>
|
||||||
|
@@ -45,6 +46,539 @@ static grub_efi_uintn_t pages;
|
||||||
|
static grub_efi_device_path_t *file_path;
|
||||||
|
static grub_efi_handle_t image_handle;
|
||||||
|
static grub_efi_char16_t *cmdline;
|
||||||
|
+static grub_int32_t shim_used;
|
||||||
|
+static grub_efi_physical_address_t shim_buffer;
|
||||||
|
+static grub_efi_uintn_t shim_pages;
|
||||||
|
+static grub_efi_loaded_image_t shim_li_bak;
|
||||||
|
+static grub_efi_status_t (*shim_entry_point) (grub_efi_handle_t image_handle,
|
||||||
|
+ grub_efi_system_table_t *systab);
|
||||||
|
+
|
||||||
|
+static const grub_uint16_t
|
||||||
|
+grub_shim_machine_type =
|
||||||
|
+#if defined(__x86_64__)
|
||||||
|
+ GRUB_PE32_MACHINE_X86_64;
|
||||||
|
+#elif defined(__aarch64__)
|
||||||
|
+ IMAGE_FILE_MACHINE_ARM64;
|
||||||
|
+#elif defined(__arm__)
|
||||||
|
+ IMAGE_FILE_MACHINE_ARMTHUMB_MIXED;
|
||||||
|
+#elif defined(__i386__) || defined(__i486__) || defined(__i686__)
|
||||||
|
+ GRUB_PE32_MACHINE_I386;
|
||||||
|
+#elif defined(__ia64__)
|
||||||
|
+ GRUB_PE32_MACHINE_IA64;
|
||||||
|
+#else
|
||||||
|
+#error this architecture is not supported by shim chainloader
|
||||||
|
+#endif
|
||||||
|
+
|
||||||
|
+static grub_efi_guid_t grub_shim_protocol_guid = GRUB_EFI_SHIM_PROTOCOL_GUID;
|
||||||
|
+
|
||||||
|
+static grub_int32_t
|
||||||
|
+grub_shim_allow_64_bit (void)
|
||||||
|
+{
|
||||||
|
+/* TODO: what is the definition for aarch64? */
|
||||||
|
+#if defined(__x86_64__)
|
||||||
|
+ return 1;
|
||||||
|
+#elif defined(__i386__) || defined(__i686__)
|
||||||
|
+/* TODO: find out what to do with in_protocol */
|
||||||
|
+ return 0;
|
||||||
|
+#else /* assuming everything else is 32-bit... */
|
||||||
|
+ return 0;
|
||||||
|
+#endif
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static grub_int32_t
|
||||||
|
+grub_shim_allow_32_bit (void)
|
||||||
|
+{
|
||||||
|
+/* TODO: what is the definition for aarch64? */
|
||||||
|
+#if defined(__x86_64__)
|
||||||
|
+/* TODO: find out what to do with in_protocol */
|
||||||
|
+ return 0;
|
||||||
|
+#elif defined(__i386__) || defined(__i686__)
|
||||||
|
+ return 1;
|
||||||
|
+#else /* assuming everything else is 32-bit... */
|
||||||
|
+ return 1;
|
||||||
|
+#endif
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static grub_int32_t
|
||||||
|
+grub_shim_image_is_64_bit (union grub_shim_optional_header_union *pe_hdr)
|
||||||
|
+{
|
||||||
|
+ /* .Magic is the same offset in all cases */
|
||||||
|
+ if (pe_hdr->pe32plus.opt_hdr.magic == GRUB_PE32_PE64_MAGIC)
|
||||||
|
+ return 1;
|
||||||
|
+ return 0;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static grub_int32_t
|
||||||
|
+grub_shim_image_is_loadable (union grub_shim_optional_header_union *pe_hdr)
|
||||||
|
+{
|
||||||
|
+ /* If the machine type doesn't match the binary, bail, unless
|
||||||
|
+ * we're in an allowed 64-on-32 scenario
|
||||||
|
+ */
|
||||||
|
+ if (pe_hdr->pe32.file_hdr.machine != grub_shim_machine_type)
|
||||||
|
+ {
|
||||||
|
+ if (!(grub_shim_machine_type == GRUB_PE32_MACHINE_I386
|
||||||
|
+ && pe_hdr->pe32.file_hdr.machine == GRUB_PE32_MACHINE_X86_64
|
||||||
|
+ && grub_shim_allow_64_bit ()))
|
||||||
|
+ return 0;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ /* If it's not a header type we recognize at all, bail */
|
||||||
|
+ switch (pe_hdr->pe32plus.opt_hdr.magic)
|
||||||
|
+ {
|
||||||
|
+ case GRUB_PE32_PE64_MAGIC:
|
||||||
|
+ case GRUB_PE32_PE32_MAGIC:
|
||||||
|
+ break;
|
||||||
|
+ default:
|
||||||
|
+ return 0;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ /* and now just check for general 64-vs-32 compatibility */
|
||||||
|
+ if (grub_shim_image_is_64_bit(pe_hdr))
|
||||||
|
+ {
|
||||||
|
+ if (grub_shim_allow_64_bit ())
|
||||||
|
+ return 1;
|
||||||
|
+ }
|
||||||
|
+ else
|
||||||
|
+ {
|
||||||
|
+ if (grub_shim_allow_32_bit ())
|
||||||
|
+ return 1;
|
||||||
|
+ }
|
||||||
|
+ return 0;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+/*
|
||||||
|
+ * Perform basic bounds checking of the intra-image pointers
|
||||||
|
+ */
|
||||||
|
+static grub_efi_uint64_t
|
||||||
|
+grub_shim_image_address (grub_addr_t image, grub_uint32_t size, grub_uint32_t addr)
|
||||||
|
+{
|
||||||
|
+ if (addr > size)
|
||||||
|
+ return 0;
|
||||||
|
+ return image + addr;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+/*
|
||||||
|
+ * Perform the actual relocation
|
||||||
|
+ */
|
||||||
|
+static grub_err_t
|
||||||
|
+grub_shim_relocate_coff (struct grub_shim_pe_coff_loader_image_context *context,
|
||||||
|
+ void *orig, void *data)
|
||||||
|
+{
|
||||||
|
+ struct grub_image_base_relocation *reloc_base, *reloc_base_end;
|
||||||
|
+ grub_efi_uint64_t adjust;
|
||||||
|
+ grub_efi_uint16_t *reloc, *reloc_end;
|
||||||
|
+ grub_uint8_t *fixup, *fixup_base, *fixup_data = NULL;
|
||||||
|
+ grub_efi_uint16_t *fixup16;
|
||||||
|
+ grub_efi_uint32_t *fixup32;
|
||||||
|
+ grub_efi_uint64_t *fixup64;
|
||||||
|
+ grub_int32_t size = context->image_size;
|
||||||
|
+ void *image_end = (char *)orig + size;
|
||||||
|
+
|
||||||
|
+ if (grub_shim_image_is_64_bit(context->pe_hdr))
|
||||||
|
+ context->pe_hdr->pe32plus.opt_hdr.image_base = (grub_efi_uint64_t)(unsigned long)data;
|
||||||
|
+ else
|
||||||
|
+ context->pe_hdr->pe32.opt_hdr.image_base = (grub_efi_uint32_t)(unsigned long)data;
|
||||||
|
+
|
||||||
|
+ reloc_base = (struct grub_image_base_relocation *)
|
||||||
|
+ grub_shim_image_address ((grub_efi_uint64_t)orig, size,
|
||||||
|
+ context->reloc_dir->rva);
|
||||||
|
+ reloc_base_end = (struct grub_image_base_relocation *)
|
||||||
|
+ grub_shim_image_address ((grub_efi_uint64_t)orig, size,
|
||||||
|
+ context->reloc_dir->rva
|
||||||
|
+ + context->reloc_dir->size - 1);
|
||||||
|
+
|
||||||
|
+ if (!reloc_base || !reloc_base_end)
|
||||||
|
+ {
|
||||||
|
+ grub_printf("Reloc table overflows binary\n");
|
||||||
|
+ return GRUB_ERR_BAD_FILE_TYPE;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ adjust = (grub_efi_uintn_t)data - context->image_address;
|
||||||
|
+
|
||||||
|
+ if (adjust == 0)
|
||||||
|
+ return GRUB_EFI_SUCCESS;
|
||||||
|
+
|
||||||
|
+ while (reloc_base < reloc_base_end)
|
||||||
|
+ {
|
||||||
|
+ reloc = (grub_efi_uint16_t *) ((grub_int8_t *) reloc_base
|
||||||
|
+ + sizeof (struct grub_image_base_relocation));
|
||||||
|
+
|
||||||
|
+ if ((reloc_base->block_size == 0)
|
||||||
|
+ || (reloc_base->block_size > context->reloc_dir->size))
|
||||||
|
+ {
|
||||||
|
+ grub_printf("Reloc block size %d is invalid\n", reloc_base->block_size);
|
||||||
|
+ return GRUB_ERR_FILE_READ_ERROR;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ reloc_end = (grub_efi_uint16_t *)
|
||||||
|
+ ((grub_uint8_t *) reloc_base + reloc_base->block_size);
|
||||||
|
+ if ((void *)reloc_end < orig || (void *)reloc_end > image_end)
|
||||||
|
+ {
|
||||||
|
+ grub_printf("Reloc entry overflows binary\n");
|
||||||
|
+ return GRUB_ERR_FILE_READ_ERROR;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ fixup_base = (grub_uint8_t *)
|
||||||
|
+ grub_shim_image_address ((grub_efi_uint64_t)data,
|
||||||
|
+ size,
|
||||||
|
+ reloc_base->virtual_address);
|
||||||
|
+ if (!fixup_base)
|
||||||
|
+ {
|
||||||
|
+ grub_printf("Invalid fixup_base\n");
|
||||||
|
+ return GRUB_ERR_FILE_READ_ERROR;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ while (reloc < reloc_end)
|
||||||
|
+ {
|
||||||
|
+ fixup = fixup_base + (*reloc & 0xFFF);
|
||||||
|
+ switch ((*reloc) >> 12)
|
||||||
|
+ {
|
||||||
|
+ case EFI_IMAGE_REL_BASED_ABSOLUTE:
|
||||||
|
+ break;
|
||||||
|
+
|
||||||
|
+ case EFI_IMAGE_REL_BASED_HIGH:
|
||||||
|
+ fixup16 = (grub_efi_uint16_t *) fixup;
|
||||||
|
+ *fixup16 = (grub_efi_uint16_t)
|
||||||
|
+ (*fixup16
|
||||||
|
+ + ((grub_efi_uint16_t) ((grub_efi_uint32_t) adjust >> 16)));
|
||||||
|
+ if (fixup_data != NULL)
|
||||||
|
+ {
|
||||||
|
+ *(grub_efi_uint16_t *) fixup_data = *fixup16;
|
||||||
|
+ fixup_data = fixup_data + sizeof (grub_efi_uint16_t);
|
||||||
|
+ }
|
||||||
|
+ break;
|
||||||
|
+
|
||||||
|
+ case EFI_IMAGE_REL_BASED_LOW:
|
||||||
|
+ fixup16 = (grub_efi_uint16_t *) fixup;
|
||||||
|
+ *fixup16 = (grub_efi_uint16_t)
|
||||||
|
+ (*fixup16 + (grub_efi_uint16_t) adjust);
|
||||||
|
+ if (fixup_data != NULL)
|
||||||
|
+ {
|
||||||
|
+ *(grub_efi_uint16_t *) fixup_data = *fixup16;
|
||||||
|
+ fixup_data = fixup_data + sizeof (grub_efi_uint16_t);
|
||||||
|
+ }
|
||||||
|
+ break;
|
||||||
|
+
|
||||||
|
+ case EFI_IMAGE_REL_BASED_HIGHLOW:
|
||||||
|
+ fixup32 = (grub_efi_uint32_t *) fixup;
|
||||||
|
+ *fixup32 = *fixup32 + (grub_efi_uint32_t) adjust;
|
||||||
|
+ if (fixup_data != NULL)
|
||||||
|
+ {
|
||||||
|
+ fixup_data = ALIGN_POINTER (fixup_data, sizeof (grub_efi_uint32_t));
|
||||||
|
+ *(grub_efi_uint32_t *)fixup_data = *fixup32;
|
||||||
|
+ fixup_data = fixup_data + sizeof (grub_efi_uint32_t);
|
||||||
|
+ }
|
||||||
|
+ break;
|
||||||
|
+
|
||||||
|
+ case EFI_IMAGE_REL_BASED_DIR64:
|
||||||
|
+ fixup64 = (grub_efi_uint64_t *) fixup;
|
||||||
|
+ *fixup64 = *fixup64 + (grub_efi_uint64_t) adjust;
|
||||||
|
+ if (fixup_data != NULL)
|
||||||
|
+ {
|
||||||
|
+ fixup_data = ALIGN_POINTER (fixup_data, sizeof(grub_efi_uint64_t));
|
||||||
|
+ *(grub_efi_uint64_t *)(fixup_data) = *fixup64;
|
||||||
|
+ fixup_data = fixup_data + sizeof(grub_efi_uint64_t);
|
||||||
|
+ }
|
||||||
|
+ break;
|
||||||
|
+
|
||||||
|
+ default:
|
||||||
|
+ grub_printf("Unknown relocation\n");
|
||||||
|
+ return GRUB_ERR_FILE_READ_ERROR;
|
||||||
|
+ }
|
||||||
|
+ reloc += 1;
|
||||||
|
+ }
|
||||||
|
+ reloc_base = (struct grub_image_base_relocation *) reloc_end;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ return GRUB_EFI_SUCCESS;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+/*
|
||||||
|
+ * Read the binary header and grab appropriate information from it
|
||||||
|
+ */
|
||||||
|
+static grub_err_t
|
||||||
|
+grub_shim_read_header(grub_efi_physical_address_t data, grub_uint32_t datasize,
|
||||||
|
+ struct grub_shim_pe_coff_loader_image_context *context)
|
||||||
|
+{
|
||||||
|
+ struct grub_dos_header *dos_hdr = (struct grub_dos_header *)data;
|
||||||
|
+ union grub_shim_optional_header_union *pe_hdr = (union grub_shim_optional_header_union *)data;
|
||||||
|
+ grub_uint64_t header_without_data_dir, section_header_offset, opt_hdr_size;
|
||||||
|
+
|
||||||
|
+ if (datasize < sizeof (pe_hdr->pe32))
|
||||||
|
+ {
|
||||||
|
+ grub_printf("Invalid image\n");
|
||||||
|
+ return GRUB_ERR_BAD_FILE_TYPE;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ if (dos_hdr->magic == EFI_IMAGE_DOS_SIGNATURE)
|
||||||
|
+ pe_hdr = (union grub_shim_optional_header_union *)((grub_uint8_t *)data
|
||||||
|
+ + dos_hdr->lfanew);
|
||||||
|
+
|
||||||
|
+ if (!grub_shim_image_is_loadable(pe_hdr))
|
||||||
|
+ {
|
||||||
|
+ grub_printf("Platform does not support this image\n");
|
||||||
|
+ return GRUB_ERR_BAD_FILE_TYPE;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ if (grub_shim_image_is_64_bit(pe_hdr))
|
||||||
|
+ {
|
||||||
|
+ context->number_of_rva_and_sizes = pe_hdr->pe32plus.opt_hdr.num_data_directories;
|
||||||
|
+ context->header_size = pe_hdr->pe32plus.opt_hdr.header_size;
|
||||||
|
+ context->image_size = pe_hdr->pe32plus.opt_hdr.image_size;
|
||||||
|
+ opt_hdr_size = sizeof(struct grub_pe64_optional_header);
|
||||||
|
+ } else
|
||||||
|
+ {
|
||||||
|
+ context->number_of_rva_and_sizes = pe_hdr->pe32.opt_hdr.num_data_directories;
|
||||||
|
+ context->header_size = pe_hdr->pe32.opt_hdr.header_size;
|
||||||
|
+ context->image_size = (grub_efi_uint64_t)pe_hdr->pe32.opt_hdr.header_size;
|
||||||
|
+ opt_hdr_size = sizeof(struct grub_pe32_optional_header);
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ context->num_sections = pe_hdr->pe32.file_hdr.num_sections;
|
||||||
|
+
|
||||||
|
+ if (GRUB_PE32_NUM_DATA_DIRECTORIES < context->number_of_rva_and_sizes)
|
||||||
|
+ {
|
||||||
|
+ grub_printf("Image header too small\n");
|
||||||
|
+ return GRUB_ERR_FILE_READ_ERROR;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ header_without_data_dir = opt_hdr_size
|
||||||
|
+ - sizeof (struct grub_pe32_data_directory)
|
||||||
|
+ * GRUB_PE32_NUM_DATA_DIRECTORIES;
|
||||||
|
+ if (((grub_efi_uint32_t)pe_hdr->pe32.file_hdr.optional_header_size
|
||||||
|
+ - header_without_data_dir) !=
|
||||||
|
+ context->number_of_rva_and_sizes * sizeof (struct grub_pe32_data_directory))
|
||||||
|
+ {
|
||||||
|
+ grub_printf("Image header overflows data directory\n");
|
||||||
|
+ return GRUB_ERR_FILE_READ_ERROR;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ section_header_offset = dos_hdr->lfanew
|
||||||
|
+ + sizeof (grub_efi_uint32_t)
|
||||||
|
+ + sizeof (struct grub_pe32_coff_header)
|
||||||
|
+ + pe_hdr->pe32.file_hdr.optional_header_size;
|
||||||
|
+ if (((grub_efi_uint32_t)context->image_size - section_header_offset)
|
||||||
|
+ / sizeof (struct grub_pe32_section_table)
|
||||||
|
+ <= context->num_sections)
|
||||||
|
+ {
|
||||||
|
+ grub_printf("Image sections overflow image size\n");
|
||||||
|
+ return GRUB_ERR_FILE_READ_ERROR;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ if ((context->header_size - section_header_offset)
|
||||||
|
+ / sizeof (struct grub_pe32_section_table)
|
||||||
|
+ < (grub_efi_uint32_t)context->num_sections)
|
||||||
|
+ {
|
||||||
|
+ grub_printf("Image sections overflow section headers\n");
|
||||||
|
+ return GRUB_ERR_FILE_READ_ERROR;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ if ((((grub_efi_uint8_t *)pe_hdr
|
||||||
|
+ - (grub_efi_uint8_t *)data)
|
||||||
|
+ + sizeof(union grub_shim_optional_header_union )) > datasize)
|
||||||
|
+ {
|
||||||
|
+ grub_printf("Invalid image\n");
|
||||||
|
+ return GRUB_ERR_BAD_FILE_TYPE;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ if (pe_hdr->te.signature != EFI_IMAGE_NT_SIGNATURE)
|
||||||
|
+ {
|
||||||
|
+ grub_printf("Unsupported image type\n");
|
||||||
|
+ return GRUB_ERR_BAD_FILE_TYPE;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ if (pe_hdr->pe32.file_hdr.characteristics & GRUB_PE32_RELOCS_STRIPPED)
|
||||||
|
+ {
|
||||||
|
+ grub_printf("Unsupported image - Relocations have been stripped\n");
|
||||||
|
+ return GRUB_ERR_BAD_FILE_TYPE;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ context->pe_hdr = pe_hdr;
|
||||||
|
+
|
||||||
|
+ if (grub_shim_image_is_64_bit(pe_hdr))
|
||||||
|
+ {
|
||||||
|
+ context->image_address = pe_hdr->pe32plus.opt_hdr.image_base;
|
||||||
|
+ context->entry_point = pe_hdr->pe32plus.opt_hdr.entry_addr;
|
||||||
|
+ context->reloc_dir = &pe_hdr->pe32plus.opt_hdr.base_relocation_table;
|
||||||
|
+ context->sec_dir = &pe_hdr->pe32plus.opt_hdr.certificate_table;
|
||||||
|
+ } else
|
||||||
|
+ {
|
||||||
|
+ context->image_address = pe_hdr->pe32.opt_hdr.image_base;
|
||||||
|
+ context->entry_point = pe_hdr->pe32.opt_hdr.entry_addr;
|
||||||
|
+ context->reloc_dir = &pe_hdr->pe32.opt_hdr.base_relocation_table;
|
||||||
|
+ context->sec_dir = &pe_hdr->pe32.opt_hdr.certificate_table;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ context->first_section = (struct grub_pe32_section_table *)
|
||||||
|
+ ((char *)pe_hdr
|
||||||
|
+ + pe_hdr->pe32.file_hdr.optional_header_size
|
||||||
|
+ + sizeof(grub_efi_uint32_t)
|
||||||
|
+ + sizeof(struct grub_pe32_coff_header));
|
||||||
|
+
|
||||||
|
+ if (context->image_size < context->header_size)
|
||||||
|
+ {
|
||||||
|
+ grub_printf("Invalid image\n");
|
||||||
|
+ return GRUB_ERR_BAD_FILE_TYPE;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ if ((unsigned long)((grub_efi_uint8_t *)context->sec_dir - (grub_efi_uint8_t *)data) >
|
||||||
|
+ (datasize - sizeof(struct grub_pe32_data_directory)))
|
||||||
|
+ {
|
||||||
|
+ grub_printf("Invalid image\n");
|
||||||
|
+ return GRUB_ERR_BAD_FILE_TYPE;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ if (context->sec_dir->rva >= datasize)
|
||||||
|
+ {
|
||||||
|
+ grub_printf("Malformed security header\n");
|
||||||
|
+ return GRUB_ERR_BAD_FILE_TYPE;
|
||||||
|
+ }
|
||||||
|
+ return GRUB_ERR_NONE;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static grub_efi_status_t
|
||||||
|
+grub_shim_verify (grub_addr_t addr, grub_ssize_t size)
|
||||||
|
+{
|
||||||
|
+ struct grub_shim_lock *shim_lock;
|
||||||
|
+ shim_lock = grub_efi_locate_protocol (&grub_shim_protocol_guid, 0);
|
||||||
|
+ if (!shim_lock)
|
||||||
|
+ {
|
||||||
|
+ grub_error (GRUB_ERR_BAD_OS, "could not load shim protocol");
|
||||||
|
+ return GRUB_EFI_UNSUPPORTED;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ return shim_lock->verify((void *) addr, size);
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static grub_err_t
|
||||||
|
+grub_shim_load_image(grub_addr_t addr, grub_ssize_t size,
|
||||||
|
+ struct grub_shim_pe_coff_loader_image_context *context)
|
||||||
|
+{
|
||||||
|
+ grub_err_t status;
|
||||||
|
+ grub_efi_status_t efi_status;
|
||||||
|
+ grub_uint32_t sect_size;
|
||||||
|
+ /* TODO: can they be unsigned? */
|
||||||
|
+ grub_int8_t *base, *end;
|
||||||
|
+ grub_int32_t i;
|
||||||
|
+ struct grub_pe32_section_table *section;
|
||||||
|
+ grub_efi_boot_services_t *b;
|
||||||
|
+
|
||||||
|
+ shim_used = 0;
|
||||||
|
+ shim_buffer = 0;
|
||||||
|
+
|
||||||
|
+ status = grub_shim_verify (addr, size);
|
||||||
|
+ if (status != GRUB_ERR_NONE)
|
||||||
|
+ {
|
||||||
|
+ grub_error (GRUB_ERR_BAD_OS, "shim verification failed");
|
||||||
|
+ return GRUB_ERR_BAD_OS;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ grub_memset(context, 0, sizeof(*context));
|
||||||
|
+ status = grub_shim_read_header (addr, size, context);
|
||||||
|
+ if (status != GRUB_ERR_NONE)
|
||||||
|
+ {
|
||||||
|
+ grub_error (GRUB_ERR_BAD_OS, "read header failed");
|
||||||
|
+ return GRUB_ERR_BAD_OS;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ /* TODO: do we need to do this with efi_allocate? */
|
||||||
|
+ shim_pages = (((grub_efi_uintn_t) context->image_size + ((1 << 12) - 1)) >> 12);
|
||||||
|
+
|
||||||
|
+ b = grub_efi_system_table->boot_services;
|
||||||
|
+ efi_status = efi_call_4 (b->allocate_pages, GRUB_EFI_ALLOCATE_ANY_PAGES,
|
||||||
|
+ GRUB_EFI_LOADER_CODE, shim_pages, &shim_buffer);
|
||||||
|
+ if (efi_status != GRUB_EFI_SUCCESS)
|
||||||
|
+ {
|
||||||
|
+ grub_error (GRUB_ERR_OUT_OF_MEMORY, N_("out of memory for shim buffer"));
|
||||||
|
+ return GRUB_ERR_OUT_OF_MEMORY;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ /* TODO: do we need the double cast? */
|
||||||
|
+ grub_memcpy ((void *) ((grub_efi_physical_address_t) shim_buffer),
|
||||||
|
+ (void *) ((grub_addr_t) addr), context->header_size);
|
||||||
|
+ /*
|
||||||
|
+ * Copy the executable's sections to their desired offsets
|
||||||
|
+ */
|
||||||
|
+ section = context->first_section;
|
||||||
|
+ for (i = 0; i < context->num_sections; i++, section++)
|
||||||
|
+ {
|
||||||
|
+ if (section->characteristics & 0x02000000)
|
||||||
|
+ /* section has EFI_IMAGE_SCN_MEM_DISCARDABLE attr set */
|
||||||
|
+ continue;
|
||||||
|
+
|
||||||
|
+ sect_size = section->virtual_size;
|
||||||
|
+
|
||||||
|
+ if (sect_size > section->raw_data_size)
|
||||||
|
+ sect_size = section->raw_data_size;
|
||||||
|
+
|
||||||
|
+ base = (grub_int8_t *)
|
||||||
|
+ grub_shim_image_address (shim_buffer, context->image_size,
|
||||||
|
+ section->virtual_address);
|
||||||
|
+ end = (grub_int8_t *)
|
||||||
|
+ grub_shim_image_address (shim_buffer, context->image_size,
|
||||||
|
+ section->virtual_address
|
||||||
|
+ + sect_size - 1);
|
||||||
|
+ if (!base || !end)
|
||||||
|
+ {
|
||||||
|
+ grub_printf("Invalid section base\n");
|
||||||
|
+ status = GRUB_ERR_BAD_FILE_TYPE;
|
||||||
|
+ goto fail;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ if (section->virtual_address < context->header_size
|
||||||
|
+ || section->raw_data_offset < context->header_size)
|
||||||
|
+ {
|
||||||
|
+ grub_printf("Section is inside image headers\n");
|
||||||
|
+ status = GRUB_ERR_BAD_FILE_TYPE;
|
||||||
|
+ goto fail;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ if (section->raw_data_size > 0)
|
||||||
|
+ /* TODO: do we need the double cast? */
|
||||||
|
+ grub_memcpy ((void *)base,
|
||||||
|
+ (void *) (((grub_addr_t) addr)
|
||||||
|
+ + section->raw_data_offset), sect_size);
|
||||||
|
+
|
||||||
|
+ if (sect_size < section->virtual_size)
|
||||||
|
+ grub_memset ((void *)(base + sect_size), 0,
|
||||||
|
+ section->virtual_size - sect_size);
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ if (context->number_of_rva_and_sizes <= EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC)
|
||||||
|
+ {
|
||||||
|
+ grub_printf("Image has no relocation entry\n");
|
||||||
|
+ status = GRUB_ERR_BAD_FILE_TYPE;
|
||||||
|
+ goto fail;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ if (context->reloc_dir->size)
|
||||||
|
+ {
|
||||||
|
+ status = grub_shim_relocate_coff (context, (void *) addr,
|
||||||
|
+ (void *) shim_buffer);
|
||||||
|
+ if (status != GRUB_ERR_NONE)
|
||||||
|
+ {
|
||||||
|
+ grub_printf("Relocation failed: [%u]\n", status);
|
||||||
|
+ status = GRUB_ERR_BAD_FILE_TYPE;
|
||||||
|
+ goto fail;
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
+ shim_entry_point = (void *)grub_shim_image_address (shim_buffer,
|
||||||
|
+ context->image_size,
|
||||||
|
+ context->entry_point);
|
||||||
|
+ if (!shim_entry_point)
|
||||||
|
+ {
|
||||||
|
+ grub_printf("Invalid entry point\n");
|
||||||
|
+ status = GRUB_ERR_BAD_FILE_TYPE;
|
||||||
|
+ goto fail;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ shim_used = 1;
|
||||||
|
+ return GRUB_ERR_NONE;
|
||||||
|
+fail:
|
||||||
|
+ efi_call_2 (b->free_pages, shim_buffer, shim_pages);
|
||||||
|
+ shim_buffer = 0;
|
||||||
|
+ return status;
|
||||||
|
+}
|
||||||
|
|
||||||
|
static grub_err_t
|
||||||
|
grub_chainloader_unload (void)
|
||||||
|
--
|
||||||
|
1.9.1
|
||||||
|
|
||||||
@@ -0,0 +1,98 @@
|
|||||||
|
From f922ac74714d01972a3c291e15f0c316b67e40eb Mon Sep 17 00:00:00 2001
|
||||||
|
From: Ricardo Neri <ricardo.neri-calderon@linux.intel.com>
|
||||||
|
Date: Fri, 27 Mar 2015 08:26:08 -0700
|
||||||
|
Subject: [PATCH 5/7] efi: chainloader: use shim to load and verify an image
|
||||||
|
|
||||||
|
Upstream-Status: Inappropriate [embedded specific]
|
||||||
|
|
||||||
|
The grub chainloader module uses the UEFI LoadImage service
|
||||||
|
to load a chainloaded binary. However, if such binary is not
|
||||||
|
signed by the UEFI certification authority, LoadImage will fail.
|
||||||
|
Under shim, we can use Machine-Owned Keys (MOKs) to verify an
|
||||||
|
image. Thus, in case LoadImage fails due to a security violation
|
||||||
|
we rely on the shim verification service. If successful, the
|
||||||
|
image is parsed and loaded.
|
||||||
|
|
||||||
|
Signed-off-by: Ricardo Neri <ricardo.neri-calderon@linux.intel.com>
|
||||||
|
---
|
||||||
|
grub-core/loader/efi/chainloader.c | 49 +++++++++++++++++++++++++++++++-------
|
||||||
|
1 file changed, 40 insertions(+), 9 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/grub-core/loader/efi/chainloader.c b/grub-core/loader/efi/chainloader.c
|
||||||
|
index bd83859..01d2ebe 100644
|
||||||
|
--- a/grub-core/loader/efi/chainloader.c
|
||||||
|
+++ b/grub-core/loader/efi/chainloader.c
|
||||||
|
@@ -733,6 +733,7 @@ grub_cmd_chainloader (grub_command_t cmd __attribute__ ((unused)),
|
||||||
|
grub_efi_loaded_image_t *loaded_image;
|
||||||
|
char *filename;
|
||||||
|
grub_efi_handle_t dev_handle = 0;
|
||||||
|
+ struct grub_shim_pe_coff_loader_image_context context;
|
||||||
|
|
||||||
|
if (argc == 0)
|
||||||
|
return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("filename expected"));
|
||||||
|
@@ -827,23 +828,53 @@ grub_cmd_chainloader (grub_command_t cmd __attribute__ ((unused)),
|
||||||
|
if (status != GRUB_EFI_SUCCESS)
|
||||||
|
{
|
||||||
|
if (status == GRUB_EFI_OUT_OF_RESOURCES)
|
||||||
|
- grub_error (GRUB_ERR_OUT_OF_MEMORY, "out of resources");
|
||||||
|
+ {
|
||||||
|
+ grub_error (GRUB_ERR_OUT_OF_MEMORY, "out of resources");
|
||||||
|
+ goto fail;
|
||||||
|
+ }
|
||||||
|
+ /* try with shim */
|
||||||
|
+ else if (status == GRUB_EFI_SECURITY_VIOLATION)
|
||||||
|
+ {
|
||||||
|
+ status = grub_shim_load_image (address, size, &context);
|
||||||
|
+ if (status != GRUB_EFI_SUCCESS)
|
||||||
|
+ {
|
||||||
|
+ grub_error (GRUB_ERR_BAD_OS, "shim cannot load image");
|
||||||
|
+ goto fail;
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
else
|
||||||
|
- grub_error (GRUB_ERR_BAD_OS, "cannot load image");
|
||||||
|
-
|
||||||
|
- goto fail;
|
||||||
|
+ {
|
||||||
|
+ grub_error (GRUB_ERR_BAD_OS, "cannot load image");
|
||||||
|
+ goto fail;
|
||||||
|
+ }
|
||||||
|
}
|
||||||
|
|
||||||
|
- /* LoadImage does not set a device handler when the image is
|
||||||
|
- loaded from memory, so it is necessary to set it explicitly here.
|
||||||
|
- This is a mess. */
|
||||||
|
- loaded_image = grub_efi_get_loaded_image (image_handle);
|
||||||
|
+ /* if we use shim, the UEFI load_image failed, thus, we borrow
|
||||||
|
+ * grub_efi_image_handle and restore it later
|
||||||
|
+ */
|
||||||
|
+ if (shim_used)
|
||||||
|
+ /* if we use shim, the UEFI load_image failed, thus, we borrow
|
||||||
|
+ grub_efi_image_handle and restore it later */
|
||||||
|
+ loaded_image = grub_efi_get_loaded_image (grub_efi_image_handle);
|
||||||
|
+ else
|
||||||
|
+ /* LoadImage does not set a device handler when the image is
|
||||||
|
+ loaded from memory, so it is necessary to set it explicitly here.
|
||||||
|
+ This is a mess. */
|
||||||
|
+ loaded_image = grub_efi_get_loaded_image (image_handle);
|
||||||
|
+
|
||||||
|
if (! loaded_image)
|
||||||
|
{
|
||||||
|
grub_error (GRUB_ERR_BAD_OS, "no loaded image available");
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
- loaded_image->device_handle = dev_handle;
|
||||||
|
+ if (shim_used)
|
||||||
|
+ {
|
||||||
|
+ grub_memcpy(&shim_li_bak, loaded_image, sizeof(shim_li_bak));
|
||||||
|
+ loaded_image->image_base = (void *)shim_buffer;
|
||||||
|
+ loaded_image->image_size = context.image_size;
|
||||||
|
+ }
|
||||||
|
+ else
|
||||||
|
+ loaded_image->device_handle = dev_handle;
|
||||||
|
|
||||||
|
grub_file_close (file);
|
||||||
|
|
||||||
|
--
|
||||||
|
1.9.1
|
||||||
|
|
||||||
@@ -0,0 +1,63 @@
|
|||||||
|
From f25778620360ccff55f3d9c1bccba14249978502 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Ricardo Neri <ricardo.neri-calderon@linux.intel.com>
|
||||||
|
Date: Fri, 27 Mar 2015 08:29:13 -0700
|
||||||
|
Subject: [PATCH 6/7] efi: chainloader: boot the image using shim
|
||||||
|
|
||||||
|
Upstream-Status: Inappropriate [embedded specific]
|
||||||
|
|
||||||
|
If the image was loaded using shim, boot the image. Given that
|
||||||
|
shim loaded the image, the UEFI firmware will not know where to
|
||||||
|
jump after the execution completes. Thus, replace the UEFI boot
|
||||||
|
service Exit with our own implementation to make sure we jump
|
||||||
|
to the instruction after the call to the entry point.
|
||||||
|
|
||||||
|
Replace the system Exit service when done.
|
||||||
|
|
||||||
|
Signed-off-by: Ricardo Neri <ricardo.neri-calderon@linux.intel.com>
|
||||||
|
---
|
||||||
|
grub-core/loader/efi/chainloader.c | 27 ++++++++++++++++++++++++++-
|
||||||
|
1 file changed, 26 insertions(+), 1 deletion(-)
|
||||||
|
|
||||||
|
diff --git a/grub-core/loader/efi/chainloader.c b/grub-core/loader/efi/chainloader.c
|
||||||
|
index 01d2ebe..1c9795c 100644
|
||||||
|
--- a/grub-core/loader/efi/chainloader.c
|
||||||
|
+++ b/grub-core/loader/efi/chainloader.c
|
||||||
|
@@ -605,9 +605,34 @@ grub_chainloader_boot (void)
|
||||||
|
grub_efi_status_t status;
|
||||||
|
grub_efi_uintn_t exit_data_size;
|
||||||
|
grub_efi_char16_t *exit_data = NULL;
|
||||||
|
+ grub_efi_loaded_image_t *loaded_image = NULL;
|
||||||
|
+ grub_efi_status_t
|
||||||
|
+ (*saved_exit) (grub_efi_handle_t image_handle,
|
||||||
|
+ grub_efi_status_t exit_status,
|
||||||
|
+ grub_efi_uintn_t exit_data_size,
|
||||||
|
+ grub_efi_char16_t *exit_data) __attribute__((noreturn));
|
||||||
|
|
||||||
|
b = grub_efi_system_table->boot_services;
|
||||||
|
- status = efi_call_3 (b->start_image, image_handle, &exit_data_size, &exit_data);
|
||||||
|
+
|
||||||
|
+ if (!shim_used)
|
||||||
|
+ status = efi_call_3 (b->start_image, image_handle, &exit_data_size, &exit_data);
|
||||||
|
+ else
|
||||||
|
+ {
|
||||||
|
+ saved_exit = grub_efi_system_table->boot_services->exit;
|
||||||
|
+ grub_efi_system_table->boot_services->exit = efi_shim_exit;
|
||||||
|
+ status = efi_call_foo(shim_entry_point,
|
||||||
|
+ (grub_efi_uint64_t)grub_efi_image_handle,
|
||||||
|
+ (grub_efi_uint64_t)grub_efi_system_table);
|
||||||
|
+ grub_efi_system_table->boot_services->exit = saved_exit;
|
||||||
|
+
|
||||||
|
+ loaded_image = grub_efi_get_loaded_image (grub_efi_image_handle);
|
||||||
|
+ if (!loaded_image)
|
||||||
|
+ /* TODO: this is serious, what to do? */
|
||||||
|
+ grub_error (GRUB_ERR_BAD_OS, "GRUB loaded image not found");
|
||||||
|
+ else
|
||||||
|
+ /* restore loaded image */
|
||||||
|
+ grub_memcpy(loaded_image, &shim_li_bak, sizeof(shim_li_bak));
|
||||||
|
+ }
|
||||||
|
if (status != GRUB_EFI_SUCCESS)
|
||||||
|
{
|
||||||
|
if (exit_data)
|
||||||
|
--
|
||||||
|
1.9.1
|
||||||
|
|
||||||
@@ -0,0 +1,43 @@
|
|||||||
|
From 70a30826d1cfb7a90c34760896dfd92b9c396f52 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Ricardo Neri <ricardo.neri-calderon@linux.intel.com>
|
||||||
|
Date: Fri, 27 Mar 2015 08:31:27 -0700
|
||||||
|
Subject: [PATCH 7/7] efi: chainloader: take care of unload undershim
|
||||||
|
|
||||||
|
Upstream-Status: Inappropriate [embedded specific]
|
||||||
|
|
||||||
|
Under shim, we use a custom buffer to put the relocated image, make
|
||||||
|
sure we free that memory when unloading.
|
||||||
|
|
||||||
|
Signed-off-by: Ricardo Neri <ricardo.neri-calderon@linux.intel.com>
|
||||||
|
---
|
||||||
|
grub-core/loader/efi/chainloader.c | 14 ++++++++++++--
|
||||||
|
1 file changed, 12 insertions(+), 2 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/grub-core/loader/efi/chainloader.c b/grub-core/loader/efi/chainloader.c
|
||||||
|
index 1c9795c..d0ceb6e 100644
|
||||||
|
--- a/grub-core/loader/efi/chainloader.c
|
||||||
|
+++ b/grub-core/loader/efi/chainloader.c
|
||||||
|
@@ -586,8 +586,18 @@ grub_chainloader_unload (void)
|
||||||
|
grub_efi_boot_services_t *b;
|
||||||
|
|
||||||
|
b = grub_efi_system_table->boot_services;
|
||||||
|
- efi_call_1 (b->unload_image, image_handle);
|
||||||
|
- efi_call_2 (b->free_pages, address, pages);
|
||||||
|
+ if (!shim_used)
|
||||||
|
+ {
|
||||||
|
+ efi_call_1 (b->unload_image, image_handle);
|
||||||
|
+ efi_call_2 (b->free_pages, address, pages);
|
||||||
|
+ }
|
||||||
|
+ else
|
||||||
|
+ {
|
||||||
|
+ if (shim_buffer)
|
||||||
|
+ {
|
||||||
|
+ efi_call_2 (b->free_pages, shim_buffer, shim_pages);
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
|
||||||
|
grub_free (file_path);
|
||||||
|
grub_free (cmdline);
|
||||||
|
--
|
||||||
|
1.9.1
|
||||||
|
|
||||||
@@ -0,0 +1,252 @@
|
|||||||
|
From e7b2efacc2d3acb48761aa2d62f943310fd70100 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Lans Zhang <jia.zhang@windriver.com>
|
||||||
|
Date: Mon, 25 Apr 2016 11:35:14 +0800
|
||||||
|
Subject: [PATCH] Fix 32-bit build failures
|
||||||
|
|
||||||
|
Upstream-Status: Pending
|
||||||
|
|
||||||
|
For 32-bit build, the 64-bit pointer should be replaced by grub_addr_t
|
||||||
|
which is compatible between 32-bit and 64-bit build.
|
||||||
|
|
||||||
|
In addition, the functions efi_shim_exit and efi_call_foo should be available
|
||||||
|
for 32-bit build.
|
||||||
|
|
||||||
|
Signed-off-by: Lans Zhang <jia.zhang@windriver.com>
|
||||||
|
---
|
||||||
|
grub-core/Makefile.core.def | 1 +
|
||||||
|
grub-core/kern/i386/efi/callwrap.S | 50 ++++++++++++++++++++++++++++++++++++++
|
||||||
|
grub-core/loader/efi/chainloader.c | 30 +++++++++++------------
|
||||||
|
include/grub/efi/api.h | 8 +++---
|
||||||
|
include/grub/efi/shim.h | 2 +-
|
||||||
|
5 files changed, 71 insertions(+), 20 deletions(-)
|
||||||
|
create mode 100644 grub-core/kern/i386/efi/callwrap.S
|
||||||
|
|
||||||
|
diff --git a/grub-core/Makefile.core.def b/grub-core/Makefile.core.def
|
||||||
|
index 39e77a4..0a78137 100644
|
||||||
|
--- a/grub-core/Makefile.core.def
|
||||||
|
+++ b/grub-core/Makefile.core.def
|
||||||
|
@@ -135,6 +135,7 @@ kernel = {
|
||||||
|
efi = term/efi/console.c;
|
||||||
|
|
||||||
|
i386_efi = kern/i386/tsc.c;
|
||||||
|
+ i386_efi = kern/i386/efi/callwrap.S;
|
||||||
|
i386_efi = kern/i386/efi/init.c;
|
||||||
|
i386_efi = bus/pci.c;
|
||||||
|
|
||||||
|
diff --git a/grub-core/kern/i386/efi/callwrap.S b/grub-core/kern/i386/efi/callwrap.S
|
||||||
|
new file mode 100644
|
||||||
|
index 0000000..c683444
|
||||||
|
--- /dev/null
|
||||||
|
+++ b/grub-core/kern/i386/efi/callwrap.S
|
||||||
|
@@ -0,0 +1,50 @@
|
||||||
|
+/* callwrap.S - wrapper for i386 efi calls */
|
||||||
|
+/*
|
||||||
|
+ * GRUB -- GRand Unified Bootloader
|
||||||
|
+ * Copyright (C) 2006,2007,2009 Free Software Foundation, Inc.
|
||||||
|
+ *
|
||||||
|
+ * GRUB is free software: you can redistribute it and/or modify
|
||||||
|
+ * it under the terms of the GNU General Public License as published by
|
||||||
|
+ * the Free Software Foundation, either version 3 of the License, or
|
||||||
|
+ * (at your option) any later version.
|
||||||
|
+ *
|
||||||
|
+ * GRUB is distributed in the hope that it will be useful,
|
||||||
|
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
+ * GNU General Public License for more details.
|
||||||
|
+ *
|
||||||
|
+ * You should have received a copy of the GNU General Public License
|
||||||
|
+ * along with GRUB. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
+ */
|
||||||
|
+
|
||||||
|
+#include <config.h>
|
||||||
|
+#include <grub/symbol.h>
|
||||||
|
+
|
||||||
|
+ .file "callwrap.S"
|
||||||
|
+ .text
|
||||||
|
+
|
||||||
|
+FUNCTION(efi_call_foo)
|
||||||
|
+ movl 12(%esp), %eax
|
||||||
|
+ movl 8(%esp), %edx
|
||||||
|
+ movl 4(%esp), %ecx
|
||||||
|
+ pushl %ebx
|
||||||
|
+ pushl %esi
|
||||||
|
+ pushl %edi
|
||||||
|
+ pushl %ebp
|
||||||
|
+ movl %esp, saved_sp
|
||||||
|
+ subl $40, %esp
|
||||||
|
+ pushl %eax
|
||||||
|
+ pushl %edx
|
||||||
|
+ call *%ecx
|
||||||
|
+
|
||||||
|
+FUNCTION(efi_shim_exit)
|
||||||
|
+ addl $48, %esp
|
||||||
|
+ movl saved_sp, %esp
|
||||||
|
+ popl %ebp
|
||||||
|
+ popl %edi
|
||||||
|
+ popl %esi
|
||||||
|
+ popl %ebx
|
||||||
|
+ ret
|
||||||
|
+
|
||||||
|
+ .data
|
||||||
|
+saved_sp: .long 0
|
||||||
|
diff --git a/grub-core/loader/efi/chainloader.c b/grub-core/loader/efi/chainloader.c
|
||||||
|
index 83769a2..e3d1138 100644
|
||||||
|
--- a/grub-core/loader/efi/chainloader.c
|
||||||
|
+++ b/grub-core/loader/efi/chainloader.c
|
||||||
|
@@ -149,7 +149,7 @@ grub_shim_image_is_loadable (union grub_shim_optional_header_union *pe_hdr)
|
||||||
|
/*
|
||||||
|
* Perform basic bounds checking of the intra-image pointers
|
||||||
|
*/
|
||||||
|
-static grub_efi_uint64_t
|
||||||
|
+static grub_addr_t
|
||||||
|
grub_shim_image_address (grub_addr_t image, grub_uint32_t size, grub_uint32_t addr)
|
||||||
|
{
|
||||||
|
if (addr > size)
|
||||||
|
@@ -208,12 +208,12 @@ grub_shim_relocate_coff (struct grub_shim_pe_coff_loader_image_context *context,
|
||||||
|
* yield the next entry in the array.
|
||||||
|
*/
|
||||||
|
reloc_base = (struct grub_image_base_relocation *)
|
||||||
|
- grub_shim_image_address ((grub_efi_uint64_t)orig, size,
|
||||||
|
+ grub_shim_image_address ((grub_addr_t)orig, size,
|
||||||
|
section->raw_data_offset);
|
||||||
|
/* reloc_base_end is the address of the first entry /past/ the
|
||||||
|
* table. */
|
||||||
|
reloc_base_end = (struct grub_image_base_relocation *)
|
||||||
|
- grub_shim_image_address ((grub_efi_uint64_t)orig, size,
|
||||||
|
+ grub_shim_image_address ((grub_addr_t)orig, size,
|
||||||
|
section->raw_data_offset
|
||||||
|
+ section->virtual_size - 1);
|
||||||
|
|
||||||
|
@@ -254,7 +254,7 @@ grub_shim_relocate_coff (struct grub_shim_pe_coff_loader_image_context *context,
|
||||||
|
}
|
||||||
|
|
||||||
|
fixup_base = (grub_uint8_t *)
|
||||||
|
- grub_shim_image_address ((grub_efi_uint64_t)data,
|
||||||
|
+ grub_shim_image_address ((grub_addr_t)data,
|
||||||
|
size,
|
||||||
|
reloc_base->virtual_address);
|
||||||
|
if (!fixup_base)
|
||||||
|
@@ -333,12 +333,12 @@ grub_shim_relocate_coff (struct grub_shim_pe_coff_loader_image_context *context,
|
||||||
|
* Read the binary header and grab appropriate information from it
|
||||||
|
*/
|
||||||
|
static grub_err_t
|
||||||
|
-grub_shim_read_header(grub_efi_physical_address_t data, grub_uint32_t datasize,
|
||||||
|
+grub_shim_read_header(grub_addr_t data, grub_uint32_t datasize,
|
||||||
|
struct grub_shim_pe_coff_loader_image_context *context)
|
||||||
|
{
|
||||||
|
struct grub_dos_header *dos_hdr = (struct grub_dos_header *)data;
|
||||||
|
union grub_shim_optional_header_union *pe_hdr = (union grub_shim_optional_header_union *)data;
|
||||||
|
- grub_uint64_t header_without_data_dir, section_header_offset, opt_hdr_size;
|
||||||
|
+ grub_efi_uintn_t header_without_data_dir, section_header_offset, opt_hdr_size;
|
||||||
|
|
||||||
|
if (datasize < sizeof (pe_hdr->pe32))
|
||||||
|
{
|
||||||
|
@@ -393,7 +393,7 @@ grub_shim_read_header(grub_efi_physical_address_t data, grub_uint32_t datasize,
|
||||||
|
+ sizeof (grub_efi_uint32_t)
|
||||||
|
+ sizeof (struct grub_pe32_coff_header)
|
||||||
|
+ pe_hdr->pe32.file_hdr.optional_header_size;
|
||||||
|
- if (((grub_efi_uint32_t)context->image_size - section_header_offset)
|
||||||
|
+ if ((context->image_size - section_header_offset)
|
||||||
|
/ sizeof (struct grub_pe32_section_table)
|
||||||
|
<= context->num_sections)
|
||||||
|
{
|
||||||
|
@@ -530,7 +530,7 @@ grub_shim_load_image(grub_addr_t addr, grub_ssize_t size,
|
||||||
|
}
|
||||||
|
|
||||||
|
/* TODO: do we need the double cast? */
|
||||||
|
- grub_memcpy ((void *) ((grub_efi_physical_address_t) shim_buffer),
|
||||||
|
+ grub_memcpy ((void *) ((grub_addr_t) shim_buffer),
|
||||||
|
(void *) ((grub_addr_t) addr), context->header_size);
|
||||||
|
|
||||||
|
reloc_base = (grub_int8_t *) grub_shim_image_address (shim_buffer, size,
|
||||||
|
@@ -553,10 +553,10 @@ grub_shim_load_image(grub_addr_t addr, grub_ssize_t size,
|
||||||
|
sect_size = section->raw_data_size;
|
||||||
|
|
||||||
|
base = (grub_int8_t *)
|
||||||
|
- grub_shim_image_address (shim_buffer, context->image_size,
|
||||||
|
+ grub_shim_image_address ((grub_addr_t) shim_buffer, context->image_size,
|
||||||
|
section->virtual_address);
|
||||||
|
end = (grub_int8_t *)
|
||||||
|
- grub_shim_image_address (shim_buffer, context->image_size,
|
||||||
|
+ grub_shim_image_address ((grub_addr_t) shim_buffer, context->image_size,
|
||||||
|
section->virtual_address
|
||||||
|
+ sect_size - 1);
|
||||||
|
|
||||||
|
@@ -619,7 +619,7 @@ grub_shim_load_image(grub_addr_t addr, grub_ssize_t size,
|
||||||
|
if (context->reloc_dir->size && reloc_section)
|
||||||
|
{
|
||||||
|
status = grub_shim_relocate_coff (context, reloc_section,
|
||||||
|
- (void *) addr, (void *) shim_buffer);
|
||||||
|
+ (void *) addr, (void *) ((grub_addr_t) shim_buffer));
|
||||||
|
if (status != GRUB_ERR_NONE)
|
||||||
|
{
|
||||||
|
grub_printf("Relocation failed: [%u]\n", status);
|
||||||
|
@@ -627,7 +627,7 @@ grub_shim_load_image(grub_addr_t addr, grub_ssize_t size,
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
- shim_entry_point = (void *)grub_shim_image_address (shim_buffer,
|
||||||
|
+ shim_entry_point = (void *)grub_shim_image_address ((grub_addr_t) shim_buffer,
|
||||||
|
context->image_size,
|
||||||
|
context->entry_point);
|
||||||
|
if (!shim_entry_point)
|
||||||
|
@@ -696,8 +696,8 @@ grub_chainloader_boot (void)
|
||||||
|
saved_exit = grub_efi_system_table->boot_services->exit;
|
||||||
|
grub_efi_system_table->boot_services->exit = efi_shim_exit;
|
||||||
|
status = efi_call_foo(shim_entry_point,
|
||||||
|
- (grub_efi_uint64_t)grub_efi_image_handle,
|
||||||
|
- (grub_efi_uint64_t)grub_efi_system_table);
|
||||||
|
+ grub_efi_image_handle,
|
||||||
|
+ grub_efi_system_table);
|
||||||
|
grub_efi_system_table->boot_services->exit = saved_exit;
|
||||||
|
|
||||||
|
loaded_image = grub_efi_get_loaded_image (grub_efi_image_handle);
|
||||||
|
@@ -970,7 +970,7 @@ grub_cmd_chainloader (grub_command_t cmd __attribute__ ((unused)),
|
||||||
|
if (shim_used)
|
||||||
|
{
|
||||||
|
grub_memcpy(&shim_li_bak, loaded_image, sizeof(shim_li_bak));
|
||||||
|
- loaded_image->image_base = (void *)shim_buffer;
|
||||||
|
+ loaded_image->image_base = (void *)(grub_addr_t) shim_buffer;
|
||||||
|
loaded_image->image_size = context.image_size;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
diff --git a/include/grub/efi/api.h b/include/grub/efi/api.h
|
||||||
|
index 374d88b..22b3543 100644
|
||||||
|
--- a/include/grub/efi/api.h
|
||||||
|
+++ b/include/grub/efi/api.h
|
||||||
|
@@ -1437,10 +1437,6 @@ typedef struct grub_efi_block_io grub_efi_block_io_t;
|
||||||
|
|
||||||
|
grub_uint64_t EXPORT_FUNC(efi_wrap_0) (void *func);
|
||||||
|
grub_uint64_t EXPORT_FUNC(efi_wrap_1) (void *func, grub_uint64_t arg1);
|
||||||
|
-grub_efi_status_t EXPORT_FUNC(efi_shim_exit) (grub_efi_handle_t handle, grub_efi_status_t exit_status,
|
||||||
|
- grub_efi_uintn_t exit_data_size, grub_efi_char16_t *exit_data) __attribute__((noreturn));
|
||||||
|
-grub_uint64_t EXPORT_FUNC(efi_call_foo) (void *func, grub_uint64_t arg1,
|
||||||
|
- grub_uint64_t arg2);
|
||||||
|
grub_uint64_t EXPORT_FUNC(efi_wrap_2) (void *func, grub_uint64_t arg1,
|
||||||
|
grub_uint64_t arg2);
|
||||||
|
grub_uint64_t EXPORT_FUNC(efi_wrap_3) (void *func, grub_uint64_t arg1,
|
||||||
|
@@ -1467,4 +1463,8 @@ grub_uint64_t EXPORT_FUNC(efi_wrap_10) (void *func, grub_uint64_t arg1,
|
||||||
|
grub_uint64_t arg10);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
+grub_efi_status_t EXPORT_FUNC(efi_shim_exit) (grub_efi_handle_t handle, grub_efi_status_t exit_status,
|
||||||
|
+ grub_efi_uintn_t exit_data_size, grub_efi_char16_t *exit_data) __attribute__((noreturn));
|
||||||
|
+grub_efi_status_t EXPORT_FUNC(efi_call_foo) (void *func, void *arg1, void *arg2);
|
||||||
|
+
|
||||||
|
#endif /* ! GRUB_EFI_API_HEADER */
|
||||||
|
diff --git a/include/grub/efi/shim.h b/include/grub/efi/shim.h
|
||||||
|
index 4b92a00..9fac90b 100644
|
||||||
|
--- a/include/grub/efi/shim.h
|
||||||
|
+++ b/include/grub/efi/shim.h
|
||||||
|
@@ -60,7 +60,7 @@ struct grub_image_base_relocation
|
||||||
|
|
||||||
|
struct grub_shim_pe_coff_loader_image_context {
|
||||||
|
grub_efi_uint64_t image_address;
|
||||||
|
- grub_efi_uint64_t image_size;
|
||||||
|
+ grub_efi_uintn_t image_size;
|
||||||
|
grub_efi_uint64_t entry_point;
|
||||||
|
grub_efi_uintn_t header_size;
|
||||||
|
grub_efi_uint16_t image_type;
|
||||||
|
--
|
||||||
|
1.9.1
|
||||||
|
|
||||||
@@ -0,0 +1,263 @@
|
|||||||
|
---
|
||||||
|
grub-core/Makefile.core.def | 8 +
|
||||||
|
grub-core/commands/efi/efivar.c | 238 ++++++++++++++++++++++++++++++++++++++++
|
||||||
|
2 files changed, 246 insertions(+)
|
||||||
|
|
||||||
|
--- /dev/null
|
||||||
|
+++ b/grub-core/commands/efi/efivar.c
|
||||||
|
@@ -0,0 +1,238 @@
|
||||||
|
+/* efivar.c - Read EFI global variables. */
|
||||||
|
+/*
|
||||||
|
+ * GRUB -- GRand Unified Bootloader
|
||||||
|
+ * Copyright (C) 2015 Free Software Foundation, Inc.
|
||||||
|
+ * Copyright (C) 2015 CloudFlare, Inc.
|
||||||
|
+ *
|
||||||
|
+ * GRUB is free software: you can redistribute it and/or modify
|
||||||
|
+ * it under the terms of the GNU General Public License as published by
|
||||||
|
+ * the Free Software Foundation, either version 3 of the License, or
|
||||||
|
+ * (at your option) any later version.
|
||||||
|
+ *
|
||||||
|
+ * GRUB is distributed in the hope that it will be useful,
|
||||||
|
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
+ * GNU General Public License for more details.
|
||||||
|
+ *
|
||||||
|
+ * You should have received a copy of the GNU General Public License
|
||||||
|
+ * along with GRUB. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
+ */
|
||||||
|
+
|
||||||
|
+#include <grub/types.h>
|
||||||
|
+#include <grub/mm.h>
|
||||||
|
+#include <grub/misc.h>
|
||||||
|
+#include <grub/efi/api.h>
|
||||||
|
+#include <grub/efi/efi.h>
|
||||||
|
+#include <grub/extcmd.h>
|
||||||
|
+#include <grub/env.h>
|
||||||
|
+#include <grub/lib/hexdump.h>
|
||||||
|
+
|
||||||
|
+GRUB_MOD_LICENSE ("GPLv3+");
|
||||||
|
+
|
||||||
|
+static const struct grub_arg_option options[] = {
|
||||||
|
+ {"format", 'f', GRUB_ARG_OPTION_OPTIONAL, N_("Parse EFI_VAR in specific format (hex, uint8, ascii, dump). Default: hex."), N_("FORMAT"), ARG_TYPE_STRING},
|
||||||
|
+ {"set", 's', GRUB_ARG_OPTION_OPTIONAL, N_("Save parsed result to environment variable (does not work with dump)."), N_("ENV_VAR"), ARG_TYPE_STRING},
|
||||||
|
+ {0, 0, 0, 0, 0, 0}
|
||||||
|
+};
|
||||||
|
+
|
||||||
|
+enum efi_var_type
|
||||||
|
+ {
|
||||||
|
+ EFI_VAR_ASCII = 0,
|
||||||
|
+ EFI_VAR_UINT8,
|
||||||
|
+ EFI_VAR_HEX,
|
||||||
|
+ EFI_VAR_DUMP,
|
||||||
|
+ EFI_VAR_INVALID = -1
|
||||||
|
+ };
|
||||||
|
+
|
||||||
|
+static enum efi_var_type
|
||||||
|
+parse_efi_var_type (const char *type)
|
||||||
|
+{
|
||||||
|
+ if (!grub_strncmp (type, "ascii", sizeof("ascii")))
|
||||||
|
+ return EFI_VAR_ASCII;
|
||||||
|
+
|
||||||
|
+ if (!grub_strncmp (type, "uint8", sizeof("uint8")))
|
||||||
|
+ return EFI_VAR_UINT8;
|
||||||
|
+
|
||||||
|
+ if (!grub_strncmp (type, "hex", sizeof("hex")))
|
||||||
|
+ return EFI_VAR_HEX;
|
||||||
|
+
|
||||||
|
+ if (!grub_strncmp (type, "dump", sizeof("dump")))
|
||||||
|
+ return EFI_VAR_DUMP;
|
||||||
|
+
|
||||||
|
+ return EFI_VAR_INVALID;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static int
|
||||||
|
+grub_print_ascii (char *str, char c)
|
||||||
|
+{
|
||||||
|
+ if (grub_iscntrl (c))
|
||||||
|
+ {
|
||||||
|
+ switch (c)
|
||||||
|
+ {
|
||||||
|
+ case '\0':
|
||||||
|
+ str[0] = '\\';
|
||||||
|
+ str[1] = '0';
|
||||||
|
+ return 2;
|
||||||
|
+
|
||||||
|
+ case '\a':
|
||||||
|
+ str[0] = '\\';
|
||||||
|
+ str[1] = 'a';
|
||||||
|
+ return 2;
|
||||||
|
+
|
||||||
|
+ case '\b':
|
||||||
|
+ str[0] = '\\';
|
||||||
|
+ str[1] = 'b';
|
||||||
|
+ return 2;
|
||||||
|
+
|
||||||
|
+ case '\f':
|
||||||
|
+ str[0] = '\\';
|
||||||
|
+ str[1] = 'f';
|
||||||
|
+ return 2;
|
||||||
|
+
|
||||||
|
+ case '\n':
|
||||||
|
+ str[0] = '\\';
|
||||||
|
+ str[1] = 'n';
|
||||||
|
+ return 2;
|
||||||
|
+
|
||||||
|
+ case '\r':
|
||||||
|
+ str[0] = '\\';
|
||||||
|
+ str[1] = 'r';
|
||||||
|
+ return 2;
|
||||||
|
+
|
||||||
|
+ case '\t':
|
||||||
|
+ str[0] = '\\';
|
||||||
|
+ str[1] = 't';
|
||||||
|
+ return 2;
|
||||||
|
+
|
||||||
|
+ case '\v':
|
||||||
|
+ str[0] = '\\';
|
||||||
|
+ str[1] = 'v';
|
||||||
|
+ return 2;
|
||||||
|
+
|
||||||
|
+ default:
|
||||||
|
+ str[0] = '.'; /* as in hexdump -C */
|
||||||
|
+ return 1;
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ str[0] = c;
|
||||||
|
+ return 1;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static grub_err_t
|
||||||
|
+grub_cmd_get_efi_var (struct grub_extcmd_context *ctxt,
|
||||||
|
+ int argc, char **args)
|
||||||
|
+{
|
||||||
|
+ struct grub_arg_list *state = ctxt->state;
|
||||||
|
+ grub_err_t status;
|
||||||
|
+ void *efi_var = NULL;
|
||||||
|
+ grub_size_t efi_var_size = 0;
|
||||||
|
+ enum efi_var_type efi_type = EFI_VAR_HEX;
|
||||||
|
+ grub_efi_guid_t global = GRUB_EFI_GLOBAL_VARIABLE_GUID;
|
||||||
|
+ char *env_var = NULL;
|
||||||
|
+ grub_size_t i;
|
||||||
|
+ char *ptr;
|
||||||
|
+
|
||||||
|
+ if (1 != argc)
|
||||||
|
+ return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("one argument expected"));
|
||||||
|
+
|
||||||
|
+ if (state[0].set)
|
||||||
|
+ efi_type = parse_efi_var_type (state[0].arg);
|
||||||
|
+
|
||||||
|
+ if (EFI_VAR_INVALID == efi_type)
|
||||||
|
+ return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("invalid format specifier"));
|
||||||
|
+
|
||||||
|
+ efi_var = grub_efi_get_variable (args[0], &global, &efi_var_size);
|
||||||
|
+ if (!efi_var || !efi_var_size)
|
||||||
|
+ {
|
||||||
|
+ status = grub_error (GRUB_ERR_READ_ERROR, N_("cannot read variable"));
|
||||||
|
+ goto err;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ switch (efi_type)
|
||||||
|
+ {
|
||||||
|
+ case EFI_VAR_ASCII:
|
||||||
|
+ env_var = grub_malloc (efi_var_size * 2 + 1);
|
||||||
|
+ if (!env_var)
|
||||||
|
+ {
|
||||||
|
+ status = grub_error (GRUB_ERR_OUT_OF_MEMORY, N_("out of memory"));
|
||||||
|
+ break;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ ptr = env_var;
|
||||||
|
+
|
||||||
|
+ for (i = 0; i < efi_var_size; i++)
|
||||||
|
+ ptr += grub_print_ascii (ptr, ((const char *)efi_var)[i]);
|
||||||
|
+ *ptr = '\0';
|
||||||
|
+ break;
|
||||||
|
+
|
||||||
|
+ case EFI_VAR_UINT8:
|
||||||
|
+ env_var = grub_malloc (4);
|
||||||
|
+ if (!env_var)
|
||||||
|
+ {
|
||||||
|
+ status = grub_error (GRUB_ERR_OUT_OF_MEMORY, N_("out of memory"));
|
||||||
|
+ break;
|
||||||
|
+ }
|
||||||
|
+ grub_snprintf (env_var, 4, "%u", *((grub_uint8_t *)efi_var));
|
||||||
|
+ break;
|
||||||
|
+
|
||||||
|
+ case EFI_VAR_HEX:
|
||||||
|
+ env_var = grub_malloc (efi_var_size * 2 + 1);
|
||||||
|
+ if (!env_var)
|
||||||
|
+ {
|
||||||
|
+ status = grub_error (GRUB_ERR_OUT_OF_MEMORY, N_("out of memory"));
|
||||||
|
+ break;
|
||||||
|
+ }
|
||||||
|
+ for (i = 0; i < efi_var_size; i++)
|
||||||
|
+ grub_snprintf (env_var + (i * 2), 3, "%02x", ((grub_uint8_t *)efi_var)[i]);
|
||||||
|
+ break;
|
||||||
|
+
|
||||||
|
+ case EFI_VAR_DUMP:
|
||||||
|
+ if (state[1].set)
|
||||||
|
+ status = grub_error (GRUB_ERR_BAD_ARGUMENT, N_("cannot set variable with dump format specifier"));
|
||||||
|
+ else
|
||||||
|
+ {
|
||||||
|
+ hexdump (0, (char *)efi_var, efi_var_size);
|
||||||
|
+ status = GRUB_ERR_NONE;
|
||||||
|
+ }
|
||||||
|
+ break;
|
||||||
|
+
|
||||||
|
+ default:
|
||||||
|
+ status = grub_error (GRUB_ERR_BUG, N_("should not happen (bug in module?)"));
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ if (efi_type != EFI_VAR_DUMP)
|
||||||
|
+ {
|
||||||
|
+ if (state[1].set)
|
||||||
|
+ status = grub_env_set (state[1].arg, env_var);
|
||||||
|
+ else
|
||||||
|
+ {
|
||||||
|
+ grub_printf ("%s\n", (const char *)env_var);
|
||||||
|
+ status = GRUB_ERR_NONE;
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+err:
|
||||||
|
+
|
||||||
|
+ if (env_var)
|
||||||
|
+ grub_free (env_var);
|
||||||
|
+
|
||||||
|
+ if (efi_var)
|
||||||
|
+ grub_free (efi_var);
|
||||||
|
+
|
||||||
|
+ return status;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static grub_extcmd_t cmd = NULL;
|
||||||
|
+
|
||||||
|
+GRUB_MOD_INIT (efivar)
|
||||||
|
+{
|
||||||
|
+ cmd = grub_register_extcmd ("get_efivar", grub_cmd_get_efi_var, 0, N_("[-f FORMAT] [-s ENV_VAR] EFI_VAR"),
|
||||||
|
+ N_("Read EFI variable and print it or save its contents to environment variable."), options);
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+GRUB_MOD_FINI (efivar)
|
||||||
|
+{
|
||||||
|
+ if (cmd)
|
||||||
|
+ grub_unregister_extcmd (cmd);
|
||||||
|
+}
|
||||||
|
--- a/grub-core/Makefile.core.def
|
||||||
|
+++ b/grub-core/Makefile.core.def
|
||||||
|
@@ -539,6 +539,14 @@ module = {
|
||||||
|
};
|
||||||
|
|
||||||
|
module = {
|
||||||
|
+ name = efivar;
|
||||||
|
+
|
||||||
|
+ common = commands/efi/efivar.c;
|
||||||
|
+
|
||||||
|
+ enable = efi;
|
||||||
|
+};
|
||||||
|
+
|
||||||
|
+module = {
|
||||||
|
name = lsacpi;
|
||||||
|
|
||||||
|
common = commands/lsacpi.c;
|
||||||
@@ -0,0 +1,62 @@
|
|||||||
|
From 9517b3173af961ea66721cfc48cd47e50a704388 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Lans Zhang <jia.zhang@windriver.com>
|
||||||
|
Date: Wed, 4 Nov 2015 17:17:06 +0800
|
||||||
|
Subject: [PATCH] Work around the failure of ExitBootServices()
|
||||||
|
|
||||||
|
ExitBootServices() will fail if any of the event handlers change
|
||||||
|
the memory map. In which case, we must be prepared to retry, but
|
||||||
|
only once so that we're guaranteed to exit on repeated failures
|
||||||
|
instead of spinning forever. This fix refers to the workaround
|
||||||
|
made by Linux kernel.
|
||||||
|
|
||||||
|
Signed-off-by: Lans Zhang <jia.zhang@windriver.com>
|
||||||
|
---
|
||||||
|
grub-core/kern/efi/mm.c | 18 +++++++++++++++++-
|
||||||
|
1 file changed, 17 insertions(+), 1 deletion(-)
|
||||||
|
|
||||||
|
diff --git a/grub-core/kern/efi/mm.c b/grub-core/kern/efi/mm.c
|
||||||
|
index 461deb0..7620a47 100644
|
||||||
|
--- a/grub-core/kern/efi/mm.c
|
||||||
|
+++ b/grub-core/kern/efi/mm.c
|
||||||
|
@@ -158,6 +158,7 @@ grub_efi_finish_boot_services (grub_efi_uintn_t *outbuf_size, void *outbuf,
|
||||||
|
{
|
||||||
|
grub_efi_boot_services_t *b;
|
||||||
|
grub_efi_status_t status;
|
||||||
|
+ int called_exit = 0;
|
||||||
|
|
||||||
|
#if defined (__i386__) || defined (__x86_64__)
|
||||||
|
const grub_uint16_t apple[] = { 'A', 'p', 'p', 'l', 'e' };
|
||||||
|
@@ -167,6 +168,7 @@ grub_efi_finish_boot_services (grub_efi_uintn_t *outbuf_size, void *outbuf,
|
||||||
|
apple, sizeof (apple)) == 0);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
+get_mem_map:
|
||||||
|
if (grub_efi_get_memory_map (&finish_mmap_size, finish_mmap_buf, &finish_key,
|
||||||
|
&finish_desc_size, &finish_desc_version) < 0)
|
||||||
|
return grub_error (GRUB_ERR_IO, "couldn't retrieve memory map");
|
||||||
|
@@ -186,7 +188,21 @@ grub_efi_finish_boot_services (grub_efi_uintn_t *outbuf_size, void *outbuf,
|
||||||
|
status = efi_call_2 (b->exit_boot_services, grub_efi_image_handle,
|
||||||
|
finish_key);
|
||||||
|
if (status != GRUB_EFI_SUCCESS)
|
||||||
|
- return grub_error (GRUB_ERR_IO, "couldn't terminate EFI services");
|
||||||
|
+ {
|
||||||
|
+ /*
|
||||||
|
+ * ExitBootServices() will fail if any of the event
|
||||||
|
+ * handlers change the memory map. In which case, we
|
||||||
|
+ * must be prepared to retry, but only once so that
|
||||||
|
+ * we're guaranteed to exit on repeated failures instead
|
||||||
|
+ * of spinning forever.
|
||||||
|
+ */
|
||||||
|
+ if (called_exit)
|
||||||
|
+ return grub_error (GRUB_ERR_IO, "couldn't terminate EFI services");
|
||||||
|
+
|
||||||
|
+ called_exit = 1;
|
||||||
|
+ grub_free (finish_mmap_buf);
|
||||||
|
+ goto get_mem_map;
|
||||||
|
+ }
|
||||||
|
|
||||||
|
grub_efi_is_finished = 1;
|
||||||
|
if (outbuf_size)
|
||||||
|
--
|
||||||
|
1.9.1
|
||||||
|
|
||||||
13
meta-efi-secure-boot/recipes-bsp/grub/grub-efi/boot-menu.inc
Normal file
13
meta-efi-secure-boot/recipes-bsp/grub/grub-efi/boot-menu.inc
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
# Note the initrd command becomes not working if the command for
|
||||||
|
# loading image is changed to the chainloader command instead of
|
||||||
|
# the linux command.
|
||||||
|
|
||||||
|
menuentry "Sample EFI boot" --unrestricted {
|
||||||
|
savedefault
|
||||||
|
set fallback=1
|
||||||
|
chainloader /bzImage root=/dev/sda2 ro rootwait initrd=/initrd
|
||||||
|
}
|
||||||
|
|
||||||
|
menuentry "Sample EFI boot (Recovery)" --unrestricted {
|
||||||
|
chainloader /bzImage_bakup root=/dev/sda2 ro rootwait initrd=/initrd_bakup
|
||||||
|
}
|
||||||
@@ -0,0 +1,219 @@
|
|||||||
|
From f6c412a240312a2be28b85905a0866288db9ffc8 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Lans Zhang <jia.zhang@windriver.com>
|
||||||
|
Date: Sun, 24 Apr 2016 19:02:28 +0800
|
||||||
|
Subject: [PATCH] chainloader: Actually find the relocations correctly and
|
||||||
|
process them that way.
|
||||||
|
|
||||||
|
Upstream-Status: Pending
|
||||||
|
|
||||||
|
Refer to a846aedd0e9dfe26ca6afaf6a1db8a54c20363c1 in shim.
|
||||||
|
|
||||||
|
Find the relocations based on the *file* address in the old binary,
|
||||||
|
because it's only the same as the virtual address some of the time.
|
||||||
|
|
||||||
|
Also perform some extra validation before processing it, and don't bail
|
||||||
|
out in /error/ if both ReloceBase and RelocEnd are null - that condition
|
||||||
|
is fine.
|
||||||
|
|
||||||
|
Signed-off-by: Lans Zhang <jia.zhang@windriver.com>
|
||||||
|
---
|
||||||
|
grub-core/loader/efi/chainloader.c | 97 +++++++++++++++++++++++++++++++-------
|
||||||
|
1 file changed, 81 insertions(+), 16 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/grub-core/loader/efi/chainloader.c b/grub-core/loader/efi/chainloader.c
|
||||||
|
index 0e84100..83769a2 100644
|
||||||
|
--- a/grub-core/loader/efi/chainloader.c
|
||||||
|
+++ b/grub-core/loader/efi/chainloader.c
|
||||||
|
@@ -162,6 +162,7 @@ grub_shim_image_address (grub_addr_t image, grub_uint32_t size, grub_uint32_t ad
|
||||||
|
*/
|
||||||
|
static grub_err_t
|
||||||
|
grub_shim_relocate_coff (struct grub_shim_pe_coff_loader_image_context *context,
|
||||||
|
+ struct grub_pe32_section_table *section,
|
||||||
|
void *orig, void *data)
|
||||||
|
{
|
||||||
|
struct grub_image_base_relocation *reloc_base, *reloc_base_end;
|
||||||
|
@@ -173,19 +174,53 @@ grub_shim_relocate_coff (struct grub_shim_pe_coff_loader_image_context *context,
|
||||||
|
grub_efi_uint64_t *fixup64;
|
||||||
|
grub_int32_t size = context->image_size;
|
||||||
|
void *image_end = (char *)orig + size;
|
||||||
|
+ int n = 0;
|
||||||
|
|
||||||
|
if (grub_shim_image_is_64_bit(context->pe_hdr))
|
||||||
|
context->pe_hdr->pe32plus.opt_hdr.image_base = (grub_efi_uint64_t)(unsigned long)data;
|
||||||
|
else
|
||||||
|
context->pe_hdr->pe32.opt_hdr.image_base = (grub_efi_uint32_t)(unsigned long)data;
|
||||||
|
|
||||||
|
+
|
||||||
|
+ /* Alright, so here's how this works:
|
||||||
|
+ *
|
||||||
|
+ * context->RelocDir gives us two things:
|
||||||
|
+ * - the VA the table of base relocation blocks are (maybe) to be
|
||||||
|
+ * mapped at (RelocDir->VirtualAddress)
|
||||||
|
+ * - the virtual size (RelocDir->Size)
|
||||||
|
+ *
|
||||||
|
+ * The .reloc section (Section here) gives us some other things:
|
||||||
|
+ * - the name! kind of. (Section->Name)
|
||||||
|
+ * - the virtual size (Section->VirtualSize), which should be the same
|
||||||
|
+ * as RelocDir->Size
|
||||||
|
+ * - the virtual address (Section->VirtualAddress)
|
||||||
|
+ * - the file section size (Section->SizeOfRawData), which is
|
||||||
|
+ * a multiple of OptHdr->FileAlignment. Only useful for image
|
||||||
|
+ * validation, not really useful for iteration bounds.
|
||||||
|
+ * - the file address (Section->PointerToRawData)
|
||||||
|
+ * - a bunch of stuff we don't use that's 0 in our binaries usually
|
||||||
|
+ * - Flags (Section->Characteristics)
|
||||||
|
+ *
|
||||||
|
+ * and then the thing that's actually at the file address is an array
|
||||||
|
+ * of EFI_IMAGE_BASE_RELOCATION structs with some values packed behind
|
||||||
|
+ * them. The SizeOfBlock field of this structure includes the
|
||||||
|
+ * structure itself, and adding it to that structure's address will
|
||||||
|
+ * yield the next entry in the array.
|
||||||
|
+ */
|
||||||
|
reloc_base = (struct grub_image_base_relocation *)
|
||||||
|
grub_shim_image_address ((grub_efi_uint64_t)orig, size,
|
||||||
|
- context->reloc_dir->rva);
|
||||||
|
+ section->raw_data_offset);
|
||||||
|
+ /* reloc_base_end is the address of the first entry /past/ the
|
||||||
|
+ * table. */
|
||||||
|
reloc_base_end = (struct grub_image_base_relocation *)
|
||||||
|
grub_shim_image_address ((grub_efi_uint64_t)orig, size,
|
||||||
|
- context->reloc_dir->rva
|
||||||
|
- + context->reloc_dir->size - 1);
|
||||||
|
+ section->raw_data_offset
|
||||||
|
+ + section->virtual_size - 1);
|
||||||
|
+
|
||||||
|
+ if (!reloc_base && !reloc_base_end)
|
||||||
|
+ {
|
||||||
|
+ return GRUB_EFI_SUCCESS;
|
||||||
|
+ }
|
||||||
|
|
||||||
|
if (!reloc_base || !reloc_base_end)
|
||||||
|
{
|
||||||
|
@@ -206,7 +241,7 @@ grub_shim_relocate_coff (struct grub_shim_pe_coff_loader_image_context *context,
|
||||||
|
if ((reloc_base->block_size == 0)
|
||||||
|
|| (reloc_base->block_size > context->reloc_dir->size))
|
||||||
|
{
|
||||||
|
- grub_printf("Reloc block size %d is invalid\n", reloc_base->block_size);
|
||||||
|
+ grub_printf("Reloc %d block size %d is invalid\n", n, reloc_base->block_size);
|
||||||
|
return GRUB_ERR_FILE_READ_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
@@ -214,7 +249,7 @@ grub_shim_relocate_coff (struct grub_shim_pe_coff_loader_image_context *context,
|
||||||
|
((grub_uint8_t *) reloc_base + reloc_base->block_size);
|
||||||
|
if ((void *)reloc_end < orig || (void *)reloc_end > image_end)
|
||||||
|
{
|
||||||
|
- grub_printf("Reloc entry overflows binary\n");
|
||||||
|
+ grub_printf("Reloc %d entry overflows binary\n", n);
|
||||||
|
return GRUB_ERR_FILE_READ_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
@@ -224,7 +259,7 @@ grub_shim_relocate_coff (struct grub_shim_pe_coff_loader_image_context *context,
|
||||||
|
reloc_base->virtual_address);
|
||||||
|
if (!fixup_base)
|
||||||
|
{
|
||||||
|
- grub_printf("Invalid fixup_base\n");
|
||||||
|
+ grub_printf("Reloc %d invalid fixup_base\n", n);
|
||||||
|
return GRUB_ERR_FILE_READ_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
@@ -282,12 +317,13 @@ grub_shim_relocate_coff (struct grub_shim_pe_coff_loader_image_context *context,
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
- grub_printf("Unknown relocation\n");
|
||||||
|
+ grub_printf("Reloc %d unknown relocation\n", n);
|
||||||
|
return GRUB_ERR_FILE_READ_ERROR;
|
||||||
|
}
|
||||||
|
reloc += 1;
|
||||||
|
}
|
||||||
|
reloc_base = (struct grub_image_base_relocation *) reloc_end;
|
||||||
|
+ n++;
|
||||||
|
}
|
||||||
|
|
||||||
|
return GRUB_EFI_SUCCESS;
|
||||||
|
@@ -458,9 +494,9 @@ grub_shim_load_image(grub_addr_t addr, grub_ssize_t size,
|
||||||
|
grub_efi_status_t efi_status;
|
||||||
|
grub_uint32_t sect_size;
|
||||||
|
/* TODO: can they be unsigned? */
|
||||||
|
- grub_int8_t *base, *end;
|
||||||
|
+ grub_int8_t *base, *end, *reloc_base, *reloc_base_end;
|
||||||
|
grub_int32_t i;
|
||||||
|
- struct grub_pe32_section_table *section;
|
||||||
|
+ struct grub_pe32_section_table *section, *reloc_section;
|
||||||
|
grub_efi_boot_services_t *b;
|
||||||
|
|
||||||
|
shim_used = 0;
|
||||||
|
@@ -496,16 +532,21 @@ grub_shim_load_image(grub_addr_t addr, grub_ssize_t size,
|
||||||
|
/* TODO: do we need the double cast? */
|
||||||
|
grub_memcpy ((void *) ((grub_efi_physical_address_t) shim_buffer),
|
||||||
|
(void *) ((grub_addr_t) addr), context->header_size);
|
||||||
|
+
|
||||||
|
+ reloc_base = (grub_int8_t *) grub_shim_image_address (shim_buffer, size,
|
||||||
|
+ context->reloc_dir->rva);
|
||||||
|
+ /* reloc_base_end here is the address of the last byte of the table */
|
||||||
|
+ reloc_base_end = (grub_int8_t *) grub_shim_image_address (shim_buffer, size,
|
||||||
|
+ context->reloc_dir->rva +
|
||||||
|
+ context->reloc_dir->size - 1);
|
||||||
|
+ reloc_section = NULL;
|
||||||
|
+
|
||||||
|
/*
|
||||||
|
* Copy the executable's sections to their desired offsets
|
||||||
|
*/
|
||||||
|
section = context->first_section;
|
||||||
|
for (i = 0; i < context->num_sections; i++, section++)
|
||||||
|
{
|
||||||
|
- if (section->characteristics & 0x02000000)
|
||||||
|
- /* section has EFI_IMAGE_SCN_MEM_DISCARDABLE attr set */
|
||||||
|
- continue;
|
||||||
|
-
|
||||||
|
sect_size = section->virtual_size;
|
||||||
|
|
||||||
|
if (sect_size > section->raw_data_size)
|
||||||
|
@@ -518,6 +559,30 @@ grub_shim_load_image(grub_addr_t addr, grub_ssize_t size,
|
||||||
|
grub_shim_image_address (shim_buffer, context->image_size,
|
||||||
|
section->virtual_address
|
||||||
|
+ sect_size - 1);
|
||||||
|
+
|
||||||
|
+ /* We do want to process .reloc, but it's often marked
|
||||||
|
+ * discardable, so we don't want to memcpy it. */
|
||||||
|
+ if (grub_memcmp (section->name, ".reloc\0\0", 8) == 0) {
|
||||||
|
+ if (reloc_section) {
|
||||||
|
+ grub_printf("Image has multiple relocation sections\n");
|
||||||
|
+ status = GRUB_ERR_BAD_FILE_TYPE;
|
||||||
|
+ goto fail;
|
||||||
|
+ }
|
||||||
|
+ /* If it has nonzero sizes, and our bounds check
|
||||||
|
+ * made sense, and the VA and size match RelocDir's
|
||||||
|
+ * versions, then we believe in this section table. */
|
||||||
|
+ if (section->raw_data_size && section->virtual_size &&
|
||||||
|
+ base && end &&
|
||||||
|
+ reloc_base == base &&
|
||||||
|
+ reloc_base_end == end) {
|
||||||
|
+ reloc_section = section;
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ if (section->characteristics & 0x02000000)
|
||||||
|
+ /* section has EFI_IMAGE_SCN_MEM_DISCARDABLE attr set */
|
||||||
|
+ continue;
|
||||||
|
+
|
||||||
|
if (!base || !end)
|
||||||
|
{
|
||||||
|
grub_printf("Invalid section base\n");
|
||||||
|
@@ -551,10 +616,10 @@ grub_shim_load_image(grub_addr_t addr, grub_ssize_t size,
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
|
||||||
|
- if (context->reloc_dir->size)
|
||||||
|
+ if (context->reloc_dir->size && reloc_section)
|
||||||
|
{
|
||||||
|
- status = grub_shim_relocate_coff (context, (void *) addr,
|
||||||
|
- (void *) shim_buffer);
|
||||||
|
+ status = grub_shim_relocate_coff (context, reloc_section,
|
||||||
|
+ (void *) addr, (void *) shim_buffer);
|
||||||
|
if (status != GRUB_ERR_NONE)
|
||||||
|
{
|
||||||
|
grub_printf("Relocation failed: [%u]\n", status);
|
||||||
|
--
|
||||||
|
1.9.1
|
||||||
|
|
||||||
@@ -0,0 +1,32 @@
|
|||||||
|
From d3a1198bfc671530ed77ad2b81b0ae4582f9378e Mon Sep 17 00:00:00 2001
|
||||||
|
From: Lans Zhang <jia.zhang@windriver.com>
|
||||||
|
Date: Sun, 24 Apr 2016 15:56:38 +0800
|
||||||
|
Subject: [PATCH] chainloader: Don't check empty section in file like .bss
|
||||||
|
|
||||||
|
Upstream-Status: Pending
|
||||||
|
|
||||||
|
Because this kind of section always has a zeroed PointerToRawData denoting
|
||||||
|
the offset to file and a valid VirtualSize denoting the real size in the
|
||||||
|
memory.
|
||||||
|
|
||||||
|
Signed-off-by: Lans Zhang <jia.zhang@windriver.com>
|
||||||
|
---
|
||||||
|
grub-core/loader/efi/chainloader.c | 2 +-
|
||||||
|
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||||
|
|
||||||
|
diff --git a/grub-core/loader/efi/chainloader.c b/grub-core/loader/efi/chainloader.c
|
||||||
|
index 2d8edc0..0e84100 100644
|
||||||
|
--- a/grub-core/loader/efi/chainloader.c
|
||||||
|
+++ b/grub-core/loader/efi/chainloader.c
|
||||||
|
@@ -526,7 +526,7 @@ grub_shim_load_image(grub_addr_t addr, grub_ssize_t size,
|
||||||
|
}
|
||||||
|
|
||||||
|
if (section->virtual_address < context->header_size
|
||||||
|
- || section->raw_data_offset < context->header_size)
|
||||||
|
+ || (section->raw_data_offset && section->raw_data_offset < context->header_size))
|
||||||
|
{
|
||||||
|
grub_printf("Section is inside image headers\n");
|
||||||
|
status = GRUB_ERR_BAD_FILE_TYPE;
|
||||||
|
--
|
||||||
|
1.9.1
|
||||||
|
|
||||||
@@ -0,0 +1,32 @@
|
|||||||
|
From b945262cdbad67e59f0d13725181862aa8a29561 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Lans Zhang <jia.zhang@windriver.com>
|
||||||
|
Date: Sun, 24 Apr 2016 12:58:10 +0800
|
||||||
|
Subject: [PATCH] chainloader: handle the unauthenticated image by shim
|
||||||
|
|
||||||
|
Upstream-Status: Pending
|
||||||
|
|
||||||
|
EFI_ACCESS_DENIED is another case whenever an unauthenticated image is loaded
|
||||||
|
by UEFI LoadImage() boot service. Shim verification protocol should handle
|
||||||
|
this case as EFI_SECURITY_VIOLATION.
|
||||||
|
|
||||||
|
Signed-off-by: Lans Zhang <jia.zhang@windriver.com>
|
||||||
|
---
|
||||||
|
grub-core/loader/efi/chainloader.c | 2 +-
|
||||||
|
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||||
|
|
||||||
|
diff --git a/grub-core/loader/efi/chainloader.c b/grub-core/loader/efi/chainloader.c
|
||||||
|
index 9f908c3..2850627 100644
|
||||||
|
--- a/grub-core/loader/efi/chainloader.c
|
||||||
|
+++ b/grub-core/loader/efi/chainloader.c
|
||||||
|
@@ -868,7 +868,7 @@ grub_cmd_chainloader (grub_command_t cmd __attribute__ ((unused)),
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
/* try with shim */
|
||||||
|
- else if (status == GRUB_EFI_SECURITY_VIOLATION)
|
||||||
|
+ else if ((status == GRUB_EFI_ACCESS_DENIED) || (status == GRUB_EFI_SECURITY_VIOLATION))
|
||||||
|
{
|
||||||
|
status = grub_shim_load_image (address, size, &context);
|
||||||
|
if (status != GRUB_EFI_SUCCESS)
|
||||||
|
--
|
||||||
|
1.9.1
|
||||||
|
|
||||||
@@ -0,0 +1,38 @@
|
|||||||
|
get_efivar -f uint8 -s secured SecureBoot
|
||||||
|
|
||||||
|
if [ "${secured}" = "1" ]; then
|
||||||
|
if [ -s "${prefix}/password.inc" ]; then
|
||||||
|
source "${prefix}/password.inc"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
get_efivar -f uint8 -s unprovisioned SetupMode
|
||||||
|
|
||||||
|
if [ "${unprovisioned}" = "1" ]; then
|
||||||
|
# Create a boot entry for Automatic Certificate Provision.
|
||||||
|
# This is especially useful for certain hardware, e.g,
|
||||||
|
# Intel NUC5i3MYHE, doedn't support to display a customized
|
||||||
|
# BIOS boot option used to launch LockDown.efi.
|
||||||
|
|
||||||
|
if [ ! "${provision_failed}" ]; then
|
||||||
|
# Secure boot was disabled in BIOS setup. Overwrite the
|
||||||
|
# behavior of normal boot.
|
||||||
|
set timeout=0
|
||||||
|
set default="Automatic Certificate Provision"
|
||||||
|
elif [ "${provision_failed}" = "0" ]; then
|
||||||
|
# The auto provision was reset in BIOS setup.
|
||||||
|
set default="Automatic Certificate Provision"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# This menu will be hidden as long as the provision succeeds.
|
||||||
|
menuentry "Automatic Certificate Provision" --unrestricted {
|
||||||
|
set provision_failed="0"
|
||||||
|
save_env provision_failed
|
||||||
|
|
||||||
|
chainloader "${prefix}/LockDown.efi"
|
||||||
|
|
||||||
|
# Refuse to unlimitedly run into auto provision if failed.
|
||||||
|
set provision_failed="1"
|
||||||
|
save_env provision_failed
|
||||||
|
}
|
||||||
|
fi
|
||||||
36
meta-efi-secure-boot/recipes-bsp/grub/grub-efi/grub-efi.cfg
Normal file
36
meta-efi-secure-boot/recipes-bsp/grub/grub-efi/grub-efi.cfg
Normal file
@@ -0,0 +1,36 @@
|
|||||||
|
set timeout=3
|
||||||
|
set color_normal="light-gray/black"
|
||||||
|
set color_highlight="light-green/blue"
|
||||||
|
|
||||||
|
# The first boot entry in normal boot.
|
||||||
|
set first_boot="0"
|
||||||
|
|
||||||
|
# The default boot entry after the first boot.
|
||||||
|
set default_boot="0"
|
||||||
|
|
||||||
|
function savedefault {
|
||||||
|
if [ "${chosen}" ]; then
|
||||||
|
next_boot="${chosen}"
|
||||||
|
save_env next_boot
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
if [ -s "${prefix}/grubenv" ]; then
|
||||||
|
load_env
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ "${next_boot}" ]; then
|
||||||
|
set default="${next_boot}"
|
||||||
|
else
|
||||||
|
set default="${first_boot}"
|
||||||
|
set next_boot="${default_boot}"
|
||||||
|
save_env next_boot
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ -s "${prefix}/efi-secure-boot.inc" ]; then
|
||||||
|
source "${prefix}/efi-secure-boot.inc"
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ -s "${prefix}/boot-menu.inc" ]; then
|
||||||
|
source "${prefix}/boot-menu.inc"
|
||||||
|
fi
|
||||||
@@ -0,0 +1,30 @@
|
|||||||
|
From cd9fbf5dc00733f8e46966e67be85ff6f9d36e6e Mon Sep 17 00:00:00 2001
|
||||||
|
From: Paul Gortmaker <paul.gortmaker@windriver.com>
|
||||||
|
Date: Fri, 10 Apr 2015 18:38:23 -0400
|
||||||
|
Subject: [PATCH] grub: enable serial console by default
|
||||||
|
|
||||||
|
Have grub go to the serial console and the default VGA console.
|
||||||
|
|
||||||
|
Signed-off-by: Paul Gortmaker <paul.gortmaker@windriver.com>
|
||||||
|
---
|
||||||
|
util/grub.d/00_header.in | 4 ++++
|
||||||
|
1 file changed, 4 insertions(+)
|
||||||
|
|
||||||
|
diff --git a/util/grub.d/00_header.in b/util/grub.d/00_header.in
|
||||||
|
index 765bfdcd30e3..86b260a2c380 100644
|
||||||
|
--- a/util/grub.d/00_header.in
|
||||||
|
+++ b/util/grub.d/00_header.in
|
||||||
|
@@ -27,6 +27,10 @@ grub_lang=`echo $LANG | cut -d . -f 1`
|
||||||
|
export TEXTDOMAIN=@PACKAGE@
|
||||||
|
export TEXTDOMAINDIR="@localedir@"
|
||||||
|
|
||||||
|
+export GRUB_TERMINAL_INPUT="console serial"
|
||||||
|
+export GRUB_TERMINAL_OUTPUT="console serial"
|
||||||
|
+export GRUB_SERIAL_COMMAND="serial --speed=115200 --unit=0 --word=8 --parity=no --stop=1"
|
||||||
|
+
|
||||||
|
. "@datadir@/@PACKAGE@/grub-mkconfig_lib"
|
||||||
|
|
||||||
|
# Do this as early as possible, since other commands might depend on it.
|
||||||
|
--
|
||||||
|
2.3.1
|
||||||
|
|
||||||
@@ -0,0 +1,709 @@
|
|||||||
|
From 46873e2c5514bf6460a2f0f39ad8f8feb8f18f68 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Lans Zhang <jia.zhang@windriver.com>
|
||||||
|
Date: Thu, 16 Mar 2017 14:49:41 +0800
|
||||||
|
Subject: [PATCH] mok2verify: support to verify non-PE file with PKCS#7
|
||||||
|
signature
|
||||||
|
|
||||||
|
MOK2 Verify Protocol is designed to verify non-PE file which cannot be
|
||||||
|
verified by the MOK verify protocol supplied by shim loader, such as grub
|
||||||
|
configuration, initrd, grub modules and so on.
|
||||||
|
|
||||||
|
Each signed file has a .p7b PKCS#7 signature file for verification. For
|
||||||
|
more details about signature format and singing tool, refer to
|
||||||
|
https://github.com/jiazhang0/SELoader and https://github.com/jiazhang0/libsign
|
||||||
|
|
||||||
|
If either kernel or initrd is not authenticated, just go to the failover
|
||||||
|
boot to avoid a much worse failure.
|
||||||
|
|
||||||
|
If any of grub config files is not authenticated, the boot process just
|
||||||
|
stops there.
|
||||||
|
|
||||||
|
In addition, the editor, rescue and cmdline modes are protected by the
|
||||||
|
combination of settings of secure boot and user authentication in order
|
||||||
|
to prevent from tampering the kernel commandline or booting unsigned
|
||||||
|
kernel.
|
||||||
|
|
||||||
|
Signed-off-by: Lans Zhang <jia.zhang@windriver.com>
|
||||||
|
---
|
||||||
|
grub-core/Makefile.core.def | 6 ++
|
||||||
|
grub-core/commands/boot.c | 14 +++-
|
||||||
|
grub-core/gfxmenu/gui_label.c | 39 ++++++++--
|
||||||
|
grub-core/lib/efi/mok2verify.c | 172 +++++++++++++++++++++++++++++++++++++++++
|
||||||
|
grub-core/loader/i386/linux.c | 80 +++++++++++++++++++
|
||||||
|
grub-core/normal/main.c | 55 ++++++++++++-
|
||||||
|
grub-core/normal/menu.c | 29 +++++--
|
||||||
|
grub-core/normal/menu_text.c | 32 ++++++--
|
||||||
|
include/grub/efi/mok2verify.h | 48 ++++++++++++
|
||||||
|
9 files changed, 447 insertions(+), 28 deletions(-)
|
||||||
|
create mode 100644 grub-core/lib/efi/mok2verify.c
|
||||||
|
create mode 100644 include/grub/efi/mok2verify.h
|
||||||
|
|
||||||
|
diff --git a/grub-core/Makefile.core.def b/grub-core/Makefile.core.def
|
||||||
|
index e9e1483..8e72251 100644
|
||||||
|
--- a/grub-core/Makefile.core.def
|
||||||
|
+++ b/grub-core/Makefile.core.def
|
||||||
|
@@ -1434,6 +1434,12 @@ module = {
|
||||||
|
};
|
||||||
|
|
||||||
|
module = {
|
||||||
|
+ name = mok2verify;
|
||||||
|
+ efi = lib/efi/mok2verify.c;
|
||||||
|
+ enable = efi;
|
||||||
|
+};
|
||||||
|
+
|
||||||
|
+module = {
|
||||||
|
name = mmap;
|
||||||
|
common = mmap/mmap.c;
|
||||||
|
x86 = mmap/i386/uppermem.c;
|
||||||
|
diff --git a/grub-core/commands/boot.c b/grub-core/commands/boot.c
|
||||||
|
index 91ec87d..5cddbb6 100644
|
||||||
|
--- a/grub-core/commands/boot.c
|
||||||
|
+++ b/grub-core/commands/boot.c
|
||||||
|
@@ -24,6 +24,9 @@
|
||||||
|
#include <grub/kernel.h>
|
||||||
|
#include <grub/mm.h>
|
||||||
|
#include <grub/i18n.h>
|
||||||
|
+#ifdef GRUB_MACHINE_EFI
|
||||||
|
+#include <grub/efi/mok2verify.h>
|
||||||
|
+#endif
|
||||||
|
|
||||||
|
GRUB_MOD_LICENSE ("GPLv3+");
|
||||||
|
|
||||||
|
@@ -143,8 +146,15 @@ grub_loader_boot (void)
|
||||||
|
struct grub_preboot *cur;
|
||||||
|
|
||||||
|
if (! grub_loader_loaded)
|
||||||
|
- return grub_error (GRUB_ERR_NO_KERNEL,
|
||||||
|
- N_("you need to load the kernel first"));
|
||||||
|
+ {
|
||||||
|
+#ifdef GRUB_MACHINE_EFI
|
||||||
|
+ if (grub_is_secured () == 1)
|
||||||
|
+ return grub_error (GRUB_ERR_BAD_OS,
|
||||||
|
+ N_("you need to load the authenticated boot components"));
|
||||||
|
+#endif
|
||||||
|
+ return grub_error (GRUB_ERR_NO_KERNEL,
|
||||||
|
+ N_("you need to load the kernel first"));
|
||||||
|
+ }
|
||||||
|
|
||||||
|
if (grub_loader_flags & GRUB_LOADER_FLAG_NORETURN)
|
||||||
|
grub_machine_fini ();
|
||||||
|
diff --git a/grub-core/gfxmenu/gui_label.c b/grub-core/gfxmenu/gui_label.c
|
||||||
|
index 637578f..84bf7d4 100644
|
||||||
|
--- a/grub-core/gfxmenu/gui_label.c
|
||||||
|
+++ b/grub-core/gfxmenu/gui_label.c
|
||||||
|
@@ -23,6 +23,9 @@
|
||||||
|
#include <grub/font.h>
|
||||||
|
#include <grub/gui_string_util.h>
|
||||||
|
#include <grub/i18n.h>
|
||||||
|
+#ifdef GRUB_MACHINE_EFI
|
||||||
|
+#include <grub/efi/mok2verify.h>
|
||||||
|
+#endif
|
||||||
|
|
||||||
|
static const char *align_options[] =
|
||||||
|
{
|
||||||
|
@@ -180,15 +183,37 @@ label_set_property (void *vself, const char *name, const char *value)
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (grub_strcmp (value, "@KEYMAP_LONG@") == 0)
|
||||||
|
- value = _("Press enter to boot the selected OS, "
|
||||||
|
- "`e' to edit the commands before booting "
|
||||||
|
- "or `c' for a command-line. ESC to return previous menu.");
|
||||||
|
+ {
|
||||||
|
+#ifdef GRUB_MACHINE_EFI
|
||||||
|
+ if (grub_is_locked () == 1)
|
||||||
|
+ value = _("Press enter to boot the selected OS. "
|
||||||
|
+ "ESC to return previous menu.");
|
||||||
|
+ else
|
||||||
|
+#endif
|
||||||
|
+ value = _("Press enter to boot the selected OS, "
|
||||||
|
+ "`e' to edit the commands before booting "
|
||||||
|
+ "or `c' for a command-line. ESC to return previous menu.");
|
||||||
|
+ }
|
||||||
|
else if (grub_strcmp (value, "@KEYMAP_MIDDLE@") == 0)
|
||||||
|
- value = _("Press enter to boot the selected OS, "
|
||||||
|
- "`e' to edit the commands before booting "
|
||||||
|
- "or `c' for a command-line.");
|
||||||
|
+ {
|
||||||
|
+#ifdef GRUB_MACHINE_EFI
|
||||||
|
+ if (grub_is_locked () == 1)
|
||||||
|
+ value = _("Press enter to boot the selected OS.");
|
||||||
|
+ else
|
||||||
|
+#endif
|
||||||
|
+ value = _("Press enter to boot the selected OS, "
|
||||||
|
+ "`e' to edit the commands before booting "
|
||||||
|
+ "or `c' for a command-line.");
|
||||||
|
+ }
|
||||||
|
else if (grub_strcmp (value, "@KEYMAP_SHORT@") == 0)
|
||||||
|
- value = _("enter: boot, `e': options, `c': cmd-line");
|
||||||
|
+ {
|
||||||
|
+#ifdef GRUB_MACHINE_EFI
|
||||||
|
+ if (grub_is_locked () == 1)
|
||||||
|
+ value = _("enter: boot");
|
||||||
|
+ else
|
||||||
|
+#endif
|
||||||
|
+ value = _("enter: boot, `e': options, `c': cmd-line");
|
||||||
|
+ }
|
||||||
|
/* FIXME: Add more templates here if needed. */
|
||||||
|
self->template = grub_strdup (value);
|
||||||
|
self->text = grub_xasprintf (value, self->value);
|
||||||
|
diff --git a/grub-core/lib/efi/mok2verify.c b/grub-core/lib/efi/mok2verify.c
|
||||||
|
new file mode 100644
|
||||||
|
index 0000000..2e48ef9
|
||||||
|
--- /dev/null
|
||||||
|
+++ b/grub-core/lib/efi/mok2verify.c
|
||||||
|
@@ -0,0 +1,172 @@
|
||||||
|
+/* mok2verify.c - MOK2 Verify Protocol support
|
||||||
|
+ *
|
||||||
|
+ * BSD 2-clause "Simplified" License
|
||||||
|
+ *
|
||||||
|
+ * Copyright (c) 2017, Lans Zhang <jia.zhang@windriver.com>
|
||||||
|
+ * All rights reserved.
|
||||||
|
+ *
|
||||||
|
+ * Redistribution and use in source and binary forms, with or without
|
||||||
|
+ * modification, are permitted provided that the following conditions are met:
|
||||||
|
+ *
|
||||||
|
+ * * Redistributions of source code must retain the above copyright notice, this
|
||||||
|
+ * list of conditions and the following disclaimer.
|
||||||
|
+ *
|
||||||
|
+ * * Redistributions in binary form must reproduce the above copyright notice,
|
||||||
|
+ * this list of conditions and the following disclaimer in the documentation
|
||||||
|
+ * and/or other materials provided with the distribution.
|
||||||
|
+ *
|
||||||
|
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||||
|
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
|
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
|
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
||||||
|
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||||
|
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||||
|
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||||
|
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||||
|
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
|
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
+ */
|
||||||
|
+
|
||||||
|
+#include <grub/loader.h>
|
||||||
|
+#include <grub/file.h>
|
||||||
|
+#include <grub/err.h>
|
||||||
|
+#include <grub/misc.h>
|
||||||
|
+#include <grub/charset.h>
|
||||||
|
+#include <grub/types.h>
|
||||||
|
+#include <grub/env.h>
|
||||||
|
+#include <grub/mm.h>
|
||||||
|
+#include <grub/efi/api.h>
|
||||||
|
+#include <grub/efi/efi.h>
|
||||||
|
+#include <grub/efi/mok2verify.h>
|
||||||
|
+
|
||||||
|
+GRUB_MOD_LICENSE ("GPLv2+");
|
||||||
|
+
|
||||||
|
+#define EFI_MOK2_VERIFY_PROTOCOL_GUID \
|
||||||
|
+ { 0x4eda73ad, 0x07aa, 0x4b7a, \
|
||||||
|
+ { 0xa1, 0x91, 0xd4, 0xd4, 0x10, 0xfb, 0x8c, 0xb4 } \
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+typedef struct efi_mok2_verify_protocol efi_mok2_verify_protocol_t;
|
||||||
|
+
|
||||||
|
+typedef grub_efi_status_t
|
||||||
|
+(*grub_efi_mok2_verify_signature) (efi_mok2_verify_protocol_t *this,
|
||||||
|
+ void *signature,
|
||||||
|
+ grub_efi_uintn_t signature_size,
|
||||||
|
+ void *data, grub_efi_uintn_t data_size);
|
||||||
|
+
|
||||||
|
+typedef grub_efi_status_t
|
||||||
|
+(*grub_efi_mok2_verify_file_buffer) (efi_mok2_verify_protocol_t *this,
|
||||||
|
+ void **data, grub_efi_uintn_t *data_size,
|
||||||
|
+ const grub_efi_char16_t *path);
|
||||||
|
+
|
||||||
|
+typedef grub_efi_status_t
|
||||||
|
+(*grub_efi_mok2_verify_file) (efi_mok2_verify_protocol_t *this,
|
||||||
|
+ const grub_efi_char16_t *path);
|
||||||
|
+
|
||||||
|
+struct efi_mok2_verify_protocol {
|
||||||
|
+ grub_efi_uint8_t revision;
|
||||||
|
+ grub_efi_mok2_verify_signature verify_signature;
|
||||||
|
+ grub_efi_mok2_verify_file_buffer verify_file_buffer;
|
||||||
|
+ grub_efi_mok2_verify_file verify_file;
|
||||||
|
+};
|
||||||
|
+
|
||||||
|
+static grub_efi_guid_t grub_efi_mok2_verify_protoco_guid = EFI_MOK2_VERIFY_PROTOCOL_GUID;
|
||||||
|
+
|
||||||
|
+int
|
||||||
|
+grub_is_secured (void)
|
||||||
|
+{
|
||||||
|
+ grub_efi_guid_t global = GRUB_EFI_GLOBAL_VARIABLE_GUID;
|
||||||
|
+ void *efi_var;
|
||||||
|
+ grub_size_t efi_var_size = 0;
|
||||||
|
+ int secured = 0;
|
||||||
|
+
|
||||||
|
+ efi_var = grub_efi_get_variable ("SecureBoot", &global, &efi_var_size);
|
||||||
|
+ if (!efi_var)
|
||||||
|
+ return grub_error (GRUB_ERR_READ_ERROR, N_("cannot read variable"));
|
||||||
|
+
|
||||||
|
+ if (efi_var_size == 1 && *(grub_uint8_t *) efi_var == 1)
|
||||||
|
+ secured = 1;
|
||||||
|
+
|
||||||
|
+ grub_free (efi_var);
|
||||||
|
+
|
||||||
|
+ return secured;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+int
|
||||||
|
+grub_is_unlockable (void)
|
||||||
|
+{
|
||||||
|
+ return !! grub_env_get ("superusers");
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+int
|
||||||
|
+grub_is_locked (void)
|
||||||
|
+{
|
||||||
|
+ return ! grub_is_unlockable () && grub_is_secured ();
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+grub_err_t
|
||||||
|
+grub_verify_file (const char *path)
|
||||||
|
+{
|
||||||
|
+ efi_mok2_verify_protocol_t *mok2;
|
||||||
|
+ grub_efi_char16_t *p;
|
||||||
|
+ grub_size_t len = grub_strlen (path);
|
||||||
|
+ grub_efi_char16_t file_path[(len + 1) * GRUB_MAX_UTF16_PER_UTF8];
|
||||||
|
+ const char *root;
|
||||||
|
+ const char *real_path;
|
||||||
|
+ grub_efi_status_t status;
|
||||||
|
+
|
||||||
|
+ mok2 = grub_efi_locate_protocol (&grub_efi_mok2_verify_protoco_guid, 0);
|
||||||
|
+ if (!mok2)
|
||||||
|
+ {
|
||||||
|
+ grub_dprintf ("mok2verify", "unable to load mok2 verify protocol\n");
|
||||||
|
+ return GRUB_ERR_NONE;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ grub_dprintf ("mok2verify", "attempting to verify the file %s ...\n", path);
|
||||||
|
+
|
||||||
|
+ real_path = path;
|
||||||
|
+ root = grub_env_get ("root");
|
||||||
|
+ if (root)
|
||||||
|
+ {
|
||||||
|
+ char *pattern;
|
||||||
|
+
|
||||||
|
+ pattern = grub_xasprintf ("(%s)", root);
|
||||||
|
+ if (!pattern)
|
||||||
|
+ return grub_errno;
|
||||||
|
+
|
||||||
|
+ if (grub_strstr (path, pattern) == path)
|
||||||
|
+ {
|
||||||
|
+ real_path = path + grub_strlen (pattern);
|
||||||
|
+ len -= grub_strlen (pattern);
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ grub_free (pattern);
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ len = grub_utf8_to_utf16 (file_path, len * GRUB_MAX_UTF16_PER_UTF8,
|
||||||
|
+ (const grub_uint8_t *) real_path, len, 0);
|
||||||
|
+ file_path[len] = 0;
|
||||||
|
+ for (p = file_path; p < file_path + len; ++p)
|
||||||
|
+ if (*p == '/')
|
||||||
|
+ *p = '\\';
|
||||||
|
+
|
||||||
|
+ status = efi_call_2 (mok2->verify_file, mok2, file_path);
|
||||||
|
+ if (status != GRUB_EFI_SUCCESS)
|
||||||
|
+ {
|
||||||
|
+ if (status == GRUB_EFI_NOT_FOUND)
|
||||||
|
+ return grub_error (GRUB_ERR_FILE_NOT_FOUND, "the specified file %s is not found",
|
||||||
|
+ path);
|
||||||
|
+ else
|
||||||
|
+ {
|
||||||
|
+ grub_printf ("failed to verify file %s (err: 0x%lx)\n",
|
||||||
|
+ path, status);
|
||||||
|
+
|
||||||
|
+ return grub_error (GRUB_ERR_ACCESS_DENIED, "the file %s is not verified",
|
||||||
|
+ path);
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ grub_dprintf ("mok2verify", "succeeded to verify file %s\n", path);
|
||||||
|
+
|
||||||
|
+ return GRUB_ERR_NONE;
|
||||||
|
+}
|
||||||
|
diff --git a/grub-core/loader/i386/linux.c b/grub-core/loader/i386/linux.c
|
||||||
|
index e2425c8..5a12444 100644
|
||||||
|
--- a/grub-core/loader/i386/linux.c
|
||||||
|
+++ b/grub-core/loader/i386/linux.c
|
||||||
|
@@ -34,6 +34,9 @@
|
||||||
|
#include <grub/i386/relocator.h>
|
||||||
|
#include <grub/i18n.h>
|
||||||
|
#include <grub/lib/cmdline.h>
|
||||||
|
+#ifdef GRUB_MACHINE_EFI
|
||||||
|
+#include <grub/efi/mok2verify.h>
|
||||||
|
+#endif
|
||||||
|
|
||||||
|
GRUB_MOD_LICENSE ("GPLv3+");
|
||||||
|
|
||||||
|
@@ -664,6 +667,55 @@ grub_linux_unload (void)
|
||||||
|
return GRUB_ERR_NONE;
|
||||||
|
}
|
||||||
|
|
||||||
|
+#ifdef GRUB_MACHINE_EFI
|
||||||
|
+static grub_err_t
|
||||||
|
+grub_verify_linux (const char *path)
|
||||||
|
+{
|
||||||
|
+ grub_file_t file;
|
||||||
|
+ grub_ssize_t size;
|
||||||
|
+ grub_uint8_t *buf = NULL;
|
||||||
|
+
|
||||||
|
+ grub_dprintf ("linux", "Verifying kernel %s\n", path);
|
||||||
|
+
|
||||||
|
+ file = grub_file_open (path);
|
||||||
|
+ if (!file)
|
||||||
|
+ return grub_errno;
|
||||||
|
+
|
||||||
|
+ size = grub_file_size (file);
|
||||||
|
+
|
||||||
|
+ buf = grub_malloc (size);
|
||||||
|
+ if (!buf)
|
||||||
|
+ goto fail;
|
||||||
|
+
|
||||||
|
+ if (grub_file_read (file, buf, size) != size)
|
||||||
|
+ {
|
||||||
|
+ if (!grub_errno)
|
||||||
|
+ grub_error (GRUB_ERR_BAD_OS, N_("premature end of kernel file %s"),
|
||||||
|
+ path);
|
||||||
|
+ goto fail;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ if (grub_verify_file (path) == GRUB_ERR_NONE)
|
||||||
|
+ grub_dprintf ("linux", "kernel %s verified\n", path);
|
||||||
|
+ else
|
||||||
|
+ grub_error (grub_errno, N_("failed to verify kernel %s"), path);
|
||||||
|
+
|
||||||
|
+fail:
|
||||||
|
+ if (buf)
|
||||||
|
+ grub_free (buf);
|
||||||
|
+
|
||||||
|
+ grub_file_close (file);
|
||||||
|
+
|
||||||
|
+ return grub_errno;
|
||||||
|
+}
|
||||||
|
+#else
|
||||||
|
+static grub_err_t
|
||||||
|
+grub_verify_linux (const char *path)
|
||||||
|
+{
|
||||||
|
+ return GRUB_ERR_NONE;
|
||||||
|
+}
|
||||||
|
+#endif
|
||||||
|
+
|
||||||
|
static grub_err_t
|
||||||
|
grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)),
|
||||||
|
int argc, char *argv[])
|
||||||
|
@@ -687,6 +739,9 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)),
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
|
||||||
|
+ if (grub_verify_linux (argv[0]))
|
||||||
|
+ goto fail;
|
||||||
|
+
|
||||||
|
file = grub_file_open (argv[0]);
|
||||||
|
if (! file)
|
||||||
|
goto fail;
|
||||||
|
@@ -1132,6 +1187,26 @@ grub_cmd_initrd (grub_command_t cmd __attribute__ ((unused)),
|
||||||
|
argv[i]);
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
+
|
||||||
|
+#ifdef GRUB_MACHINE_EFI
|
||||||
|
+ grub_dprintf ("linux", "Verifying initrd %s, addr=0x%lx, size=0x%lx\n",
|
||||||
|
+ argv[i], (unsigned long) ptr, (unsigned long) cursize);
|
||||||
|
+
|
||||||
|
+ /*
|
||||||
|
+ * XXX: use grub_verify_file_buffer (argv[i], ptr, cursize) in future
|
||||||
|
+ */
|
||||||
|
+ err = grub_verify_file (argv[i]);
|
||||||
|
+ if (err == GRUB_ERR_NONE)
|
||||||
|
+ {
|
||||||
|
+ grub_dprintf ("linux", "initrd %s verified\n", argv[i]);
|
||||||
|
+ }
|
||||||
|
+ else
|
||||||
|
+ {
|
||||||
|
+ grub_error (err, N_("failed to verify initrd %s"), argv[i]);
|
||||||
|
+ goto fail;
|
||||||
|
+ }
|
||||||
|
+#endif
|
||||||
|
+
|
||||||
|
ptr += cursize;
|
||||||
|
grub_memset (ptr, 0, ALIGN_UP_OVERHEAD (cursize, 4));
|
||||||
|
ptr += ALIGN_UP_OVERHEAD (cursize, 4);
|
||||||
|
@@ -1149,6 +1224,11 @@ grub_cmd_initrd (grub_command_t cmd __attribute__ ((unused)),
|
||||||
|
grub_file_close (files[i]);
|
||||||
|
grub_free (files);
|
||||||
|
|
||||||
|
+#ifdef GRUB_MACHINE_EFI
|
||||||
|
+ /* An unauthenticated initrd always causes a complete boot failure. */
|
||||||
|
+ if (grub_is_secured () == 1 && grub_errno != GRUB_ERR_NONE)
|
||||||
|
+ grub_loader_unset();
|
||||||
|
+#endif
|
||||||
|
return grub_errno;
|
||||||
|
}
|
||||||
|
|
||||||
|
diff --git a/grub-core/normal/main.c b/grub-core/normal/main.c
|
||||||
|
index 13473ec..f11ce2a 100644
|
||||||
|
--- a/grub-core/normal/main.c
|
||||||
|
+++ b/grub-core/normal/main.c
|
||||||
|
@@ -32,6 +32,9 @@
|
||||||
|
#include <grub/i18n.h>
|
||||||
|
#include <grub/charset.h>
|
||||||
|
#include <grub/script_sh.h>
|
||||||
|
+#ifdef GRUB_MACHINE_EFI
|
||||||
|
+#include <grub/efi/mok2verify.h>
|
||||||
|
+#endif
|
||||||
|
|
||||||
|
GRUB_MOD_LICENSE ("GPLv3+");
|
||||||
|
|
||||||
|
@@ -233,6 +236,16 @@ grub_normal_init_page (struct grub_term_output *term)
|
||||||
|
|
||||||
|
grub_term_cls (term);
|
||||||
|
|
||||||
|
+#ifdef GRUB_MACHINE_EFI
|
||||||
|
+ if (grub_is_secured () == 1)
|
||||||
|
+ {
|
||||||
|
+ if (grub_is_unlockable () == 1)
|
||||||
|
+ msg = _("GNU GRUB version %s (UNLOCKABLE)");
|
||||||
|
+ else
|
||||||
|
+ msg = _("GNU GRUB version %s (LOCKED)");
|
||||||
|
+ }
|
||||||
|
+#endif
|
||||||
|
+
|
||||||
|
msg_formatted = grub_xasprintf (msg, PACKAGE_VERSION);
|
||||||
|
if (!msg_formatted)
|
||||||
|
return;
|
||||||
|
@@ -294,6 +307,24 @@ grub_normal_execute (const char *config, int nested, int batch)
|
||||||
|
|
||||||
|
if (config)
|
||||||
|
{
|
||||||
|
+#ifdef GRUB_MACHINE_EFI
|
||||||
|
+ grub_err_t err;
|
||||||
|
+
|
||||||
|
+ err = grub_verify_file (config);
|
||||||
|
+ if (err != GRUB_ERR_NONE)
|
||||||
|
+ {
|
||||||
|
+ grub_error (err, "Security Violation: grub.cfg failed to load");
|
||||||
|
+ grub_print_error ();
|
||||||
|
+
|
||||||
|
+ /* System halt. */
|
||||||
|
+ asm volatile ("cli");
|
||||||
|
+ while (1)
|
||||||
|
+ {
|
||||||
|
+ asm volatile ("hlt");
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
+#endif
|
||||||
|
+
|
||||||
|
menu = read_config_file (config);
|
||||||
|
|
||||||
|
/* Ignore any error. */
|
||||||
|
@@ -317,7 +348,10 @@ grub_enter_normal_mode (const char *config)
|
||||||
|
{
|
||||||
|
nested_level++;
|
||||||
|
grub_normal_execute (config, 0, 0);
|
||||||
|
- grub_cmdline_run (0);
|
||||||
|
+#ifdef GRUB_MACHINE_EFI
|
||||||
|
+ if (grub_is_locked () == 0)
|
||||||
|
+#endif
|
||||||
|
+ grub_cmdline_run (0);
|
||||||
|
nested_level--;
|
||||||
|
if (grub_normal_exit_level)
|
||||||
|
grub_normal_exit_level--;
|
||||||
|
@@ -352,6 +386,18 @@ grub_cmd_normal (struct grub_command *cmd __attribute__ ((unused)),
|
||||||
|
grub_enter_normal_mode (argv[0]);
|
||||||
|
|
||||||
|
quit:
|
||||||
|
+#ifdef GRUB_MACHINE_EFI
|
||||||
|
+ if (grub_is_secured () == 1)
|
||||||
|
+ {
|
||||||
|
+ /* Never return back to the rescue mode */
|
||||||
|
+ asm volatile ("cli");
|
||||||
|
+
|
||||||
|
+ while (1)
|
||||||
|
+ {
|
||||||
|
+ asm volatile ("hlt");
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
+#endif
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
@@ -527,8 +573,11 @@ GRUB_MOD_INIT(normal)
|
||||||
|
/* Register a command "normal" for the rescue mode. */
|
||||||
|
grub_register_command ("normal", grub_cmd_normal,
|
||||||
|
0, N_("Enter normal mode."));
|
||||||
|
- grub_register_command ("normal_exit", grub_cmd_normal_exit,
|
||||||
|
- 0, N_("Exit from normal mode."));
|
||||||
|
+#ifdef GRUB_MACHINE_EFI
|
||||||
|
+ if (grub_is_secured () == 0)
|
||||||
|
+#endif
|
||||||
|
+ grub_register_command ("normal_exit", grub_cmd_normal_exit,
|
||||||
|
+ 0, N_("Exit from normal mode."));
|
||||||
|
|
||||||
|
/* Reload terminal colors when these variables are written to. */
|
||||||
|
grub_register_variable_hook ("color_normal", NULL, grub_env_write_color_normal);
|
||||||
|
diff --git a/grub-core/normal/menu.c b/grub-core/normal/menu.c
|
||||||
|
index 7e0a158..5ed9670 100644
|
||||||
|
--- a/grub-core/normal/menu.c
|
||||||
|
+++ b/grub-core/normal/menu.c
|
||||||
|
@@ -32,6 +32,9 @@
|
||||||
|
#include <grub/script_sh.h>
|
||||||
|
#include <grub/gfxterm.h>
|
||||||
|
#include <grub/dl.h>
|
||||||
|
+#ifdef GRUB_MACHINE_EFI
|
||||||
|
+#include <grub/efi/mok2verify.h>
|
||||||
|
+#endif
|
||||||
|
|
||||||
|
/* Time to delay after displaying an error message about a default/fallback
|
||||||
|
entry failing to boot. */
|
||||||
|
@@ -633,18 +636,28 @@ run_menu (grub_menu_t menu, int nested, int *auto_boot)
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'c':
|
||||||
|
- menu_fini ();
|
||||||
|
- grub_cmdline_run (1);
|
||||||
|
- goto refresh;
|
||||||
|
+#ifdef GRUB_MACHINE_EFI
|
||||||
|
+ if (grub_is_locked () == 0)
|
||||||
|
+#endif
|
||||||
|
+ {
|
||||||
|
+ menu_fini ();
|
||||||
|
+ grub_cmdline_run (1);
|
||||||
|
+ goto refresh;
|
||||||
|
+ }
|
||||||
|
|
||||||
|
case 'e':
|
||||||
|
- menu_fini ();
|
||||||
|
+#ifdef GRUB_MACHINE_EFI
|
||||||
|
+ if (grub_is_locked () == 0)
|
||||||
|
+#endif
|
||||||
|
{
|
||||||
|
- grub_menu_entry_t e = grub_menu_get_entry (menu, current_entry);
|
||||||
|
- if (e)
|
||||||
|
- grub_menu_entry_run (e);
|
||||||
|
+ menu_fini ();
|
||||||
|
+ {
|
||||||
|
+ grub_menu_entry_t e = grub_menu_get_entry (menu, current_entry);
|
||||||
|
+ if (e)
|
||||||
|
+ grub_menu_entry_run (e);
|
||||||
|
+ }
|
||||||
|
+ goto refresh;
|
||||||
|
}
|
||||||
|
- goto refresh;
|
||||||
|
|
||||||
|
default:
|
||||||
|
{
|
||||||
|
diff --git a/grub-core/normal/menu_text.c b/grub-core/normal/menu_text.c
|
||||||
|
index 1687c28..6e4fbfb 100644
|
||||||
|
--- a/grub-core/normal/menu_text.c
|
||||||
|
+++ b/grub-core/normal/menu_text.c
|
||||||
|
@@ -27,6 +27,9 @@
|
||||||
|
#include <grub/menu_viewer.h>
|
||||||
|
#include <grub/i18n.h>
|
||||||
|
#include <grub/charset.h>
|
||||||
|
+#ifdef GRUB_MACHINE_EFI
|
||||||
|
+#include <grub/efi/mok2verify.h>
|
||||||
|
+#endif
|
||||||
|
|
||||||
|
static grub_uint8_t grub_color_menu_normal;
|
||||||
|
static grub_uint8_t grub_color_menu_highlight;
|
||||||
|
@@ -179,19 +182,32 @@ command-line or ESC to discard edits and return to the GRUB menu."),
|
||||||
|
|
||||||
|
if (nested)
|
||||||
|
{
|
||||||
|
+#ifdef GRUB_MACHINE_EFI
|
||||||
|
+ if (grub_is_locked () == 1)
|
||||||
|
+ msg = _("Press enter to boot the selected OS. "
|
||||||
|
+ "ESC to return previous menu.");
|
||||||
|
+ else
|
||||||
|
+#endif
|
||||||
|
+ msg = _("Press enter to boot the selected OS, "
|
||||||
|
+ "`e' to edit the commands before booting "
|
||||||
|
+ "or `c' for a command-line. ESC to return previous menu.");
|
||||||
|
+
|
||||||
|
ret += grub_print_message_indented_real
|
||||||
|
- (_("Press enter to boot the selected OS, "
|
||||||
|
- "`e' to edit the commands before booting "
|
||||||
|
- "or `c' for a command-line. ESC to return previous menu."),
|
||||||
|
- STANDARD_MARGIN, STANDARD_MARGIN, term, dry_run);
|
||||||
|
+ (msg, STANDARD_MARGIN, STANDARD_MARGIN, term, dry_run);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
+#ifdef GRUB_MACHINE_EFI
|
||||||
|
+ if (grub_is_locked () == 1)
|
||||||
|
+ msg = _("Press enter to boot the selected OS.");
|
||||||
|
+ else
|
||||||
|
+#endif
|
||||||
|
+ msg = _("Press enter to boot the selected OS, "
|
||||||
|
+ "`e' to edit the commands before booting "
|
||||||
|
+ "or `c' for a command-line.");
|
||||||
|
+
|
||||||
|
ret += grub_print_message_indented_real
|
||||||
|
- (_("Press enter to boot the selected OS, "
|
||||||
|
- "`e' to edit the commands before booting "
|
||||||
|
- "or `c' for a command-line."),
|
||||||
|
- STANDARD_MARGIN, STANDARD_MARGIN, term, dry_run);
|
||||||
|
+ (msg, STANDARD_MARGIN, STANDARD_MARGIN, term, dry_run);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
diff --git a/include/grub/efi/mok2verify.h b/include/grub/efi/mok2verify.h
|
||||||
|
new file mode 100644
|
||||||
|
index 0000000..98ef2d4
|
||||||
|
--- /dev/null
|
||||||
|
+++ b/include/grub/efi/mok2verify.h
|
||||||
|
@@ -0,0 +1,48 @@
|
||||||
|
+/*
|
||||||
|
+ * mok2verify.h - interface to MOK2 Verify Protocol
|
||||||
|
+ *
|
||||||
|
+ * BSD 2-clause "Simplified" License
|
||||||
|
+ *
|
||||||
|
+ * Copyright (c) 2017, Lans Zhang <jia.zhang@windriver.com>
|
||||||
|
+ * All rights reserved.
|
||||||
|
+ *
|
||||||
|
+ * Redistribution and use in source and binary forms, with or without
|
||||||
|
+ * modification, are permitted provided that the following conditions are met:
|
||||||
|
+ *
|
||||||
|
+ * * Redistributions of source code must retain the above copyright notice, this
|
||||||
|
+ * list of conditions and the following disclaimer.
|
||||||
|
+ *
|
||||||
|
+ * * Redistributions in binary form must reproduce the above copyright notice,
|
||||||
|
+ * this list of conditions and the following disclaimer in the documentation
|
||||||
|
+ * and/or other materials provided with the distribution.
|
||||||
|
+ *
|
||||||
|
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||||
|
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
|
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
|
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
||||||
|
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||||
|
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||||
|
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||||
|
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||||
|
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
|
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
+ */
|
||||||
|
+
|
||||||
|
+#ifndef GRUB_EFI_MOK2_VERIFY_HEADER
|
||||||
|
+#define GRUB_EFI_MOK2_VERIFY_HEADER 1
|
||||||
|
+
|
||||||
|
+#include <grub/types.h>
|
||||||
|
+
|
||||||
|
+int
|
||||||
|
+EXPORT_FUNC (grub_is_secured) (void);
|
||||||
|
+
|
||||||
|
+int
|
||||||
|
+EXPORT_FUNC (grub_is_locked) (void);
|
||||||
|
+
|
||||||
|
+int
|
||||||
|
+EXPORT_FUNC (grub_is_unlockable) (void);
|
||||||
|
+
|
||||||
|
+grub_err_t
|
||||||
|
+EXPORT_FUNC (grub_verify_file) (const char *path);
|
||||||
|
+
|
||||||
|
+#endif /* ! GRUB_EFI_MOK2_VERIFY_HEADER */
|
||||||
|
--
|
||||||
|
2.7.4
|
||||||
|
|
||||||
@@ -0,0 +1,2 @@
|
|||||||
|
set superusers="root"
|
||||||
|
password_pbkdf2 root grub.pbkdf2.sha512.10000.4039B6F2AC3D0E349479D2573BC4B206E022E9308DBCBA8F42FBBBF64B699B79A5426CE58503ACBB37CA4116CA1B95C89BEC5F804CB91C8ED5A7381C9E03EDE8.69E763E475CF993A6B4954F9BA863E45E8DFAF2BCEBEAAB21319DC766287FA1A621807F6E2AAD9277A6BA3B9B56A14C0918C441EE47BE304D23ADA562CA018E9
|
||||||
@@ -0,0 +1,22 @@
|
|||||||
|
---
|
||||||
|
grub-core/term/efi/console.c | 9 ++++++---
|
||||||
|
1 file changed, 6 insertions(+), 3 deletions(-)
|
||||||
|
|
||||||
|
--- a/grub-core/term/efi/console.c
|
||||||
|
+++ b/grub-core/term/efi/console.c
|
||||||
|
@@ -124,9 +124,12 @@ grub_console_getkey (struct grub_term_in
|
||||||
|
if (status != GRUB_EFI_SUCCESS)
|
||||||
|
return GRUB_TERM_NO_KEY;
|
||||||
|
|
||||||
|
- if (key.scan_code == 0)
|
||||||
|
- return key.unicode_char;
|
||||||
|
- else if (key.scan_code < ARRAY_SIZE (efi_codes))
|
||||||
|
+ if (key.scan_code == 0) {
|
||||||
|
+ if (key.unicode_char < 0x20 && key.unicode_char != 0 && key.unicode_char != '\t' && key.unicode_char != '\b' && key.unicode_char != '\n' && key.unicode_char != '\r')
|
||||||
|
+ return GRUB_TERM_CTRL | (key.unicode_char - 1 + 'a');
|
||||||
|
+ else
|
||||||
|
+ return key.unicode_char;
|
||||||
|
+ } else if (key.scan_code < ARRAY_SIZE (efi_codes))
|
||||||
|
return efi_codes[key.scan_code];
|
||||||
|
|
||||||
|
return GRUB_TERM_NO_KEY;
|
||||||
146
meta-efi-secure-boot/recipes-bsp/grub/grub-efi_2.02.bbappend
Normal file
146
meta-efi-secure-boot/recipes-bsp/grub/grub-efi_2.02.bbappend
Normal file
@@ -0,0 +1,146 @@
|
|||||||
|
FILESEXTRAPATHS_prepend := "${THISDIR}/grub-efi:"
|
||||||
|
|
||||||
|
EXTRA_SRC_URI = " \
|
||||||
|
${@'file://efi-secure-boot.inc file://password.inc' if d.getVar('UEFI_SB', True) == '1' else ''} \
|
||||||
|
"
|
||||||
|
|
||||||
|
SRC_URI += " \
|
||||||
|
file://0001-pe32.h-add-header-structures-for-TE-and-DOS-executab.patch \
|
||||||
|
file://0002-shim-add-needed-data-structures.patch \
|
||||||
|
file://0003-efi-chainloader-implement-an-UEFI-Exit-service-for-s.patch \
|
||||||
|
file://0004-efi-chainloader-port-shim-to-grub.patch \
|
||||||
|
file://0005-efi-chainloader-use-shim-to-load-and-verify-an-image.patch \
|
||||||
|
file://0006-efi-chainloader-boot-the-image-using-shim.patch \
|
||||||
|
file://0007-efi-chainloader-take-care-of-unload-undershim.patch \
|
||||||
|
file://chainloader-handle-the-unauthenticated-image-by-shim.patch \
|
||||||
|
file://chainloader-Don-t-check-empty-section-in-file-like-..patch \
|
||||||
|
file://chainloader-Actually-find-the-relocations-correctly-.patch \
|
||||||
|
file://Grub-get-and-set-efi-variables.patch \
|
||||||
|
file://Fix-32-bit-build-failures.patch;apply=0 \
|
||||||
|
file://Work-around-the-failure-of-ExitBootServices.patch;apply=0 \
|
||||||
|
file://serial-redirect-control-x-fix.patch;apply=0 \
|
||||||
|
file://mok2verify-support-to-verify-non-PE-file-with-PKCS-7.patch;apply=0 \
|
||||||
|
file://grub-efi.cfg \
|
||||||
|
file://boot-menu.inc \
|
||||||
|
${EXTRA_SRC_URI} \
|
||||||
|
"
|
||||||
|
|
||||||
|
EFI_BOOT_PATH = "/boot/efi/EFI/BOOT"
|
||||||
|
|
||||||
|
#GRUB_BUILDIN_append = " chain ${@'efivar mok2verify password_pbkdf2' if d.getVar('UEFI_SB', True) == '1' else ''}"
|
||||||
|
GRUB_BUILDIN_append += " chain ${@'efivar password_pbkdf2' if d.getVar('UEFI_SB', True) == '1' else ''}"
|
||||||
|
|
||||||
|
# For efi_call_foo and efi_shim_exit
|
||||||
|
CFLAGS_append = " -fno-toplevel-reorder"
|
||||||
|
|
||||||
|
# Set a default root specifier.
|
||||||
|
inherit user-key-store
|
||||||
|
|
||||||
|
python __anonymous () {
|
||||||
|
if d.getVar('UEFI_SB', True) != "1":
|
||||||
|
return
|
||||||
|
|
||||||
|
# Override the default filename if efi-secure-boot enabled.
|
||||||
|
# grub-efi must be renamed as grub${arch}.efi for working with shim
|
||||||
|
# or SELoader.
|
||||||
|
import re
|
||||||
|
|
||||||
|
target = d.getVar('TARGET_ARCH', True)
|
||||||
|
if target == "x86_64":
|
||||||
|
grubimage = "grubx64.efi"
|
||||||
|
elif re.match('i.86', target):
|
||||||
|
grubimage = "grubia32.efi"
|
||||||
|
else:
|
||||||
|
raise bb.parse.SkipPackage("grub-efi is incompatible with target %s" % target)
|
||||||
|
|
||||||
|
d.setVar("GRUB_IMAGE", grubimage)
|
||||||
|
}
|
||||||
|
|
||||||
|
do_compile_append_class-native() {
|
||||||
|
make grub-editenv
|
||||||
|
}
|
||||||
|
|
||||||
|
do_install_append_class-native() {
|
||||||
|
install -m 0755 grub-editenv "${D}${bindir}"
|
||||||
|
}
|
||||||
|
|
||||||
|
do_install_append_class-target() {
|
||||||
|
local menu="${WORKDIR}/boot-menu.inc"
|
||||||
|
|
||||||
|
# Enable the default IMA rules if IMA is enabled and encrypted-storage is
|
||||||
|
# disabled. This is because unseal operation will fail when any PCR is
|
||||||
|
# extended due to updating the aggregate integrity value by the default
|
||||||
|
# IMA rules.
|
||||||
|
[ x"${IMA}" = x"1" -a x"${@bb.utils.contains('DISTRO_FEATURES', 'encrypted-storage', '1', '0', d)}" != x"1" ] && {
|
||||||
|
! grep -q "ima_policy=tcb" "$menu" &&
|
||||||
|
sed -i 's/^\s*chainloader\s\+.*bzImage.*/& ima_policy=tcb/g' "$menu"
|
||||||
|
}
|
||||||
|
|
||||||
|
[ x"${UEFI_SB}" = x"1" ] && {
|
||||||
|
# Don't allow to load the detached initramfs if the bundled kernel used.
|
||||||
|
[ x"${INITRAMFS_IMAGE_BUNDLE}" = x"1" ] &&
|
||||||
|
sed -i 's/\(^\s*chainloader\s\+.*bzImage.*\)\s\+initrd=[^[:space:]]*\(.*\)/\1\2/g' "$menu"
|
||||||
|
}
|
||||||
|
|
||||||
|
# Install the stacked grub configs.
|
||||||
|
install -d "${D}${EFI_BOOT_PATH}"
|
||||||
|
install -m 0600 "${WORKDIR}/grub-efi.cfg" "${D}${EFI_BOOT_PATH}/grub.cfg"
|
||||||
|
install -m 0600 "$menu" "${D}${EFI_BOOT_PATH}"
|
||||||
|
[ x"${UEFI_SB}" = x"1" ] && {
|
||||||
|
install -m 0600 "${WORKDIR}/efi-secure-boot.inc" "${D}${EFI_BOOT_PATH}"
|
||||||
|
install -m 0600 "${WORKDIR}/password.inc" "${D}${EFI_BOOT_PATH}"
|
||||||
|
}
|
||||||
|
|
||||||
|
# Create the initial environment block with empty item.
|
||||||
|
grub-editenv "${D}${EFI_BOOT_PATH}/grubenv" create
|
||||||
|
|
||||||
|
install -d "${D}${EFI_BOOT_PATH}/${GRUB_TARGET}-efi"
|
||||||
|
grub-mkimage -p /EFI/BOOT -d "./grub-core" \
|
||||||
|
-O "${GRUB_TARGET}-efi" -o "${B}/${GRUB_IMAGE}" \
|
||||||
|
${GRUB_BUILDIN}
|
||||||
|
|
||||||
|
install -m 0644 "${B}/${GRUB_IMAGE}" "${D}${EFI_BOOT_PATH}/${GRUB_IMAGE}"
|
||||||
|
|
||||||
|
# Install the modules to grub-efi's search path
|
||||||
|
make -C grub-core install DESTDIR="${D}${EFI_BOOT_PATH}" pkglibdir=""
|
||||||
|
|
||||||
|
# Remove .module
|
||||||
|
rm -f ${D}${EFI_BOOT_PATH}/${GRUB_TARGET}-efi/*.module
|
||||||
|
}
|
||||||
|
|
||||||
|
fakeroot python do_sign_class-target() {
|
||||||
|
image_dir = d.getVar('D', True)
|
||||||
|
efi_boot_path = d.getVar('EFI_BOOT_PATH', True)
|
||||||
|
grub_image = d.getVar('GRUB_IMAGE', True)
|
||||||
|
dir = image_dir + efi_boot_path + '/'
|
||||||
|
|
||||||
|
sb_sign(dir + grub_image, dir + grub_image, d)
|
||||||
|
uks_sel_sign(dir + 'grub.cfg', d)
|
||||||
|
uks_sel_sign(dir + 'boot-menu.inc', d)
|
||||||
|
|
||||||
|
if d.getVar('UEFI_SB', True) == "1":
|
||||||
|
uks_sel_sign(dir + 'efi-secure-boot.inc', d)
|
||||||
|
uks_sel_sign(dir + 'password.inc', d)
|
||||||
|
}
|
||||||
|
|
||||||
|
fakeroot python do_sign() {
|
||||||
|
}
|
||||||
|
addtask sign after do_install before do_deploy do_package
|
||||||
|
|
||||||
|
# Override the do_deploy() in oe-core.
|
||||||
|
do_deploy_class-target() {
|
||||||
|
install -m 0644 "${D}${EFI_BOOT_PATH}/${GRUB_IMAGE}" "${DEPLOYDIR}"
|
||||||
|
|
||||||
|
install -d "${DEPLOYDIR}/efi-unsigned"
|
||||||
|
install -m 0644 "${B}/${GRUB_IMAGE}" "${DEPLOYDIR}/efi-unsigned"
|
||||||
|
cp -af "${D}${EFI_BOOT_PATH}/${GRUB_TARGET}-efi" "${DEPLOYDIR}/efi-unsigned"
|
||||||
|
}
|
||||||
|
|
||||||
|
FILES_${PN} += "/boot/efi"
|
||||||
|
|
||||||
|
CONFFILES_${PN} += " \
|
||||||
|
${EFI_BOOT_PATH}/grub.cfg \
|
||||||
|
${EFI_BOOT_PATH}/grubenv \
|
||||||
|
${EFI_BOOT_PATH}/boot-menu.inc \
|
||||||
|
${EFI_BOOT_PATH}/efi-secure-boot.inc \
|
||||||
|
"
|
||||||
94
meta-efi-secure-boot/recipes-bsp/seloader/seloader_git.bb
Normal file
94
meta-efi-secure-boot/recipes-bsp/seloader/seloader_git.bb
Normal file
@@ -0,0 +1,94 @@
|
|||||||
|
SUMMARY = "The bootloader capable of authenticating the PE and non-PE files."
|
||||||
|
DESCRIPTION = "The SELoader is designed to authenticate the non-PE files, \
|
||||||
|
such as grub configuration, initrd, grub modules, which cannot be verified \
|
||||||
|
by the MOK Verify Protocol registered by shim loader. \
|
||||||
|
\
|
||||||
|
In order to conveniently authenticate the PE file with gBS->LoadImage() \
|
||||||
|
and gBS->StartImage(), the SELoader hooks EFI Security2 Architectural \
|
||||||
|
Protocol and employs MOK Verify Protocol to verify the PE file. If only \
|
||||||
|
UEFI Secure Boot is enabled, the SELoader just simplily calls \
|
||||||
|
gBS->LoadImage() and gBS->StartImage() to allow BIOS to verify PE file. \
|
||||||
|
\
|
||||||
|
The SELoader publishes MOK2 Verify Protocol which provides a flexible \
|
||||||
|
interface to allow the bootloader to verify the file, file buffer or \
|
||||||
|
memory buffer without knowing the file format. \
|
||||||
|
"
|
||||||
|
HOMEPAGE = "https://github.com/jiazhang0/SELoader.git"
|
||||||
|
SECTION = "bootloaders"
|
||||||
|
|
||||||
|
LICENSE = "BSD-3-Clause"
|
||||||
|
LIC_FILES_CHKSUM = "file://LICENSE;md5=d9bf404642f21afb4ad89f95d7bc91ee"
|
||||||
|
PR = "r0"
|
||||||
|
SRC_URI = " \
|
||||||
|
git://github.com/jiazhang0/SELoader.git \
|
||||||
|
"
|
||||||
|
SRCREV = "32e3292c33603f319354aac273938fe63897a8da"
|
||||||
|
PV = "0.4.5+git${SRCPV}"
|
||||||
|
|
||||||
|
COMPATIBLE_HOST = '(i.86|x86_64).*-linux'
|
||||||
|
|
||||||
|
inherit deploy user-key-store
|
||||||
|
|
||||||
|
S = "${WORKDIR}/git"
|
||||||
|
DEPENDS += " \
|
||||||
|
gnu-efi sbsigntool-native \
|
||||||
|
"
|
||||||
|
|
||||||
|
EFI_ARCH_x86 = "ia32"
|
||||||
|
EFI_ARCH_x86-64 = "x64"
|
||||||
|
|
||||||
|
EXTRA_OEMAKE = " \
|
||||||
|
CROSS_COMPILE="${TARGET_PREFIX}" \
|
||||||
|
SBSIGN=${STAGING_BINDIR_NATIVE}/sbsign \
|
||||||
|
gnuefi_libdir=${STAGING_LIBDIR} \
|
||||||
|
LIB_GCC="`${CC} -print-libgcc-file-name`" \
|
||||||
|
"
|
||||||
|
|
||||||
|
PARALLEL_MAKE = ""
|
||||||
|
|
||||||
|
EFI_TARGET = "/boot/efi/EFI/BOOT"
|
||||||
|
FILES_${PN} += "${EFI_TARGET}"
|
||||||
|
|
||||||
|
python do_sign() {
|
||||||
|
sb_sign(d.expand('${B}/Src/Efi/SELoader.efi'), d.expand('${B}/Src/Efi/SELoader.efi.signed'), d)
|
||||||
|
sb_sign(d.expand('${B}/Bin/Hash2DxeCrypto.efi'), d.expand('${B}/Bin/Hash2DxeCrypto.efi.signed'), d)
|
||||||
|
sb_sign(d.expand('${B}/Bin/Pkcs7VerifyDxe.efi'), d.expand('${B}/Bin/Pkcs7VerifyDxe.efi.signed'), d)
|
||||||
|
}
|
||||||
|
addtask sign after do_compile before do_install
|
||||||
|
|
||||||
|
do_install() {
|
||||||
|
install -d ${D}${EFI_TARGET}
|
||||||
|
|
||||||
|
oe_runmake install EFI_DESTDIR=${D}${EFI_TARGET}
|
||||||
|
|
||||||
|
if [ x"${UEFI_SB}" = x"1" ]; then
|
||||||
|
if [ x"${MOK_SB}" != x"1" ]; then
|
||||||
|
mv ${D}${EFI_TARGET}/SELoader${EFI_ARCH}.efi \
|
||||||
|
${D}${EFI_TARGET}/boot${EFI_ARCH}.efi
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
do_deploy() {
|
||||||
|
# Deploy the unsigned images for manual signing
|
||||||
|
install -d ${DEPLOYDIR}/efi-unsigned
|
||||||
|
|
||||||
|
install -m 0600 ${B}/Src/Efi/SELoader.efi \
|
||||||
|
${DEPLOYDIR}/efi-unsigned/SELoader${EFI_ARCH}.efi
|
||||||
|
install -m 0600 ${B}/Bin/Hash2DxeCrypto.efi ${DEPLOYDIR}/efi-unsigned/
|
||||||
|
install -m 0600 ${B}/Bin/Pkcs7VerifyDxe.efi ${DEPLOYDIR}/efi-unsigned/
|
||||||
|
|
||||||
|
# Deploy the signed images
|
||||||
|
if [ x"${UEFI_SB}" = x"1" -a x"${MOK_SB}" != x"1" ]; then
|
||||||
|
SEL_NAME=boot
|
||||||
|
else
|
||||||
|
SEL_NAME=SELoader
|
||||||
|
fi
|
||||||
|
install -m 0600 ${D}${EFI_TARGET}/${SEL_NAME}${EFI_ARCH}.efi \
|
||||||
|
${DEPLOYDIR}/${SEL_NAME}${EFI_ARCH}.efi
|
||||||
|
install -m 0600 ${D}${EFI_TARGET}/Hash2DxeCrypto.efi \
|
||||||
|
${DEPLOYDIR}/Hash2DxeCrypto.efi
|
||||||
|
install -m 0600 ${D}${EFI_TARGET}/Pkcs7VerifyDxe.efi \
|
||||||
|
${DEPLOYDIR}/Pkcs7VerifyDxe.efi
|
||||||
|
}
|
||||||
|
addtask deploy after do_install before do_build
|
||||||
@@ -0,0 +1,156 @@
|
|||||||
|
From 88806eaf9f1726d06eb4e88f12ca86537dbaab75 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Lans Zhang <jia.zhang@windriver.com>
|
||||||
|
Date: Fri, 16 Jun 2017 15:16:35 +0800
|
||||||
|
Subject: [PATCH] shim: allow to verify sha1 digest for Authenticode
|
||||||
|
|
||||||
|
Upstream-Status: Pending
|
||||||
|
|
||||||
|
The EV code signing cert sometimes doesn't comply the Authenticode spec to
|
||||||
|
employ a sha256 digest.
|
||||||
|
|
||||||
|
Signed-off-by: Lans Zhang <jia.zhang@windriver.com>
|
||||||
|
---
|
||||||
|
shim.c | 48 +++++++++++++++++++++++++++++++++++-------------
|
||||||
|
1 file changed, 35 insertions(+), 13 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/shim.c b/shim.c
|
||||||
|
index 6e040c4..384ccd7 100644
|
||||||
|
--- a/shim.c
|
||||||
|
+++ b/shim.c
|
||||||
|
@@ -428,7 +428,8 @@ static BOOLEAN verify_eku(UINT8 *Cert, UINTN CertSize)
|
||||||
|
static CHECK_STATUS check_db_cert_in_ram(EFI_SIGNATURE_LIST *CertList,
|
||||||
|
UINTN dbsize,
|
||||||
|
WIN_CERTIFICATE_EFI_PKCS *data,
|
||||||
|
- UINT8 *hash)
|
||||||
|
+ UINT8 *hash,
|
||||||
|
+ UINTN hashsize)
|
||||||
|
{
|
||||||
|
EFI_SIGNATURE_DATA *Cert;
|
||||||
|
UINTN CertSize;
|
||||||
|
@@ -445,7 +446,7 @@ static CHECK_STATUS check_db_cert_in_ram(EFI_SIGNATURE_LIST *CertList,
|
||||||
|
data->Hdr.dwLength - sizeof(data->Hdr),
|
||||||
|
Cert->SignatureData,
|
||||||
|
CertSize,
|
||||||
|
- hash, SHA256_DIGEST_SIZE);
|
||||||
|
+ hash, hashsize);
|
||||||
|
if (IsFound)
|
||||||
|
return DATA_FOUND;
|
||||||
|
}
|
||||||
|
@@ -462,7 +463,7 @@ static CHECK_STATUS check_db_cert_in_ram(EFI_SIGNATURE_LIST *CertList,
|
||||||
|
}
|
||||||
|
|
||||||
|
static CHECK_STATUS check_db_cert(CHAR16 *dbname, EFI_GUID guid,
|
||||||
|
- WIN_CERTIFICATE_EFI_PKCS *data, UINT8 *hash)
|
||||||
|
+ WIN_CERTIFICATE_EFI_PKCS *data, UINT8 *hash, UINTN hashsize)
|
||||||
|
{
|
||||||
|
CHECK_STATUS rc;
|
||||||
|
EFI_STATUS efi_status;
|
||||||
|
@@ -477,7 +478,7 @@ static CHECK_STATUS check_db_cert(CHAR16 *dbname, EFI_GUID guid,
|
||||||
|
|
||||||
|
CertList = (EFI_SIGNATURE_LIST *)db;
|
||||||
|
|
||||||
|
- rc = check_db_cert_in_ram(CertList, dbsize, data, hash);
|
||||||
|
+ rc = check_db_cert_in_ram(CertList, dbsize, data, hash, hashsize);
|
||||||
|
|
||||||
|
FreePool(db);
|
||||||
|
|
||||||
|
@@ -571,7 +572,8 @@ static EFI_STATUS check_blacklist (WIN_CERTIFICATE_EFI_PKCS *cert,
|
||||||
|
DATA_FOUND)
|
||||||
|
return EFI_SECURITY_VIOLATION;
|
||||||
|
if (cert && check_db_cert_in_ram(dbx, vendor_dbx_size, cert,
|
||||||
|
- sha256hash) == DATA_FOUND)
|
||||||
|
+ sha256hash, SHA256_DIGEST_SIZE) ==
|
||||||
|
+ DATA_FOUND)
|
||||||
|
return EFI_SECURITY_VIOLATION;
|
||||||
|
|
||||||
|
if (check_db_hash(L"dbx", secure_var, sha256hash, SHA256_DIGEST_SIZE,
|
||||||
|
@@ -580,14 +582,14 @@ static EFI_STATUS check_blacklist (WIN_CERTIFICATE_EFI_PKCS *cert,
|
||||||
|
if (check_db_hash(L"dbx", secure_var, sha1hash, SHA1_DIGEST_SIZE,
|
||||||
|
EFI_CERT_SHA1_GUID) == DATA_FOUND)
|
||||||
|
return EFI_SECURITY_VIOLATION;
|
||||||
|
- if (cert && check_db_cert(L"dbx", secure_var, cert, sha256hash) ==
|
||||||
|
+ if (cert && check_db_cert(L"dbx", secure_var, cert, sha256hash, SHA256_DIGEST_SIZE) ==
|
||||||
|
DATA_FOUND)
|
||||||
|
return EFI_SECURITY_VIOLATION;
|
||||||
|
if (check_db_hash(L"MokListX", shim_var, sha256hash, SHA256_DIGEST_SIZE,
|
||||||
|
EFI_CERT_SHA256_GUID) == DATA_FOUND) {
|
||||||
|
return EFI_SECURITY_VIOLATION;
|
||||||
|
}
|
||||||
|
- if (cert && check_db_cert(L"MokListX", shim_var, cert, sha256hash) ==
|
||||||
|
+ if (cert && check_db_cert(L"MokListX", shim_var, cert, sha256hash, SHA256_DIGEST_SIZE) ==
|
||||||
|
DATA_FOUND) {
|
||||||
|
return EFI_SECURITY_VIOLATION;
|
||||||
|
}
|
||||||
|
@@ -622,7 +624,7 @@ static EFI_STATUS check_whitelist (WIN_CERTIFICATE_EFI_PKCS *cert,
|
||||||
|
update_verification_method(VERIFIED_BY_HASH);
|
||||||
|
return EFI_SUCCESS;
|
||||||
|
}
|
||||||
|
- if (cert && check_db_cert(L"db", secure_var, cert, sha256hash)
|
||||||
|
+ if (cert && check_db_cert(L"db", secure_var, cert, sha256hash, SHA256_DIGEST_SIZE)
|
||||||
|
== DATA_FOUND) {
|
||||||
|
verification_method = VERIFIED_BY_CERT;
|
||||||
|
update_verification_method(VERIFIED_BY_CERT);
|
||||||
|
@@ -636,7 +638,7 @@ static EFI_STATUS check_whitelist (WIN_CERTIFICATE_EFI_PKCS *cert,
|
||||||
|
update_verification_method(VERIFIED_BY_HASH);
|
||||||
|
return EFI_SUCCESS;
|
||||||
|
}
|
||||||
|
- if (cert && check_db_cert(L"MokList", shim_var, cert, sha256hash) ==
|
||||||
|
+ if (cert && check_db_cert(L"MokList", shim_var, cert, sha256hash, SHA256_DIGEST_SIZE) ==
|
||||||
|
DATA_FOUND) {
|
||||||
|
verification_method = VERIFIED_BY_CERT;
|
||||||
|
update_verification_method(VERIFIED_BY_CERT);
|
||||||
|
@@ -1020,27 +1022,47 @@ static EFI_STATUS verify_buffer (char *data, int datasize,
|
||||||
|
/*
|
||||||
|
* Check against the shim build key
|
||||||
|
*/
|
||||||
|
- if (sizeof(shim_cert) &&
|
||||||
|
- AuthenticodeVerify(cert->CertData,
|
||||||
|
+ if (sizeof(shim_cert)) {
|
||||||
|
+ if (AuthenticodeVerify(cert->CertData,
|
||||||
|
cert->Hdr.dwLength - sizeof(cert->Hdr),
|
||||||
|
shim_cert, sizeof(shim_cert), sha256hash,
|
||||||
|
SHA256_DIGEST_SIZE)) {
|
||||||
|
update_verification_method(VERIFIED_BY_CERT);
|
||||||
|
status = EFI_SUCCESS;
|
||||||
|
return status;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ if (AuthenticodeVerify(cert->CertData,
|
||||||
|
+ cert->Hdr.dwLength - sizeof(cert->Hdr),
|
||||||
|
+ shim_cert, sizeof(shim_cert), sha1hash,
|
||||||
|
+ SHA1_DIGEST_SIZE)) {
|
||||||
|
+ update_verification_method(VERIFIED_BY_CERT);
|
||||||
|
+ status = EFI_SUCCESS;
|
||||||
|
+ return status;
|
||||||
|
+ }
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* And finally, check against shim's built-in key
|
||||||
|
*/
|
||||||
|
- if (vendor_cert_size &&
|
||||||
|
- AuthenticodeVerify(cert->CertData,
|
||||||
|
+ if (vendor_cert_size) {
|
||||||
|
+ if (AuthenticodeVerify(cert->CertData,
|
||||||
|
cert->Hdr.dwLength - sizeof(cert->Hdr),
|
||||||
|
vendor_cert, vendor_cert_size,
|
||||||
|
sha256hash, SHA256_DIGEST_SIZE)) {
|
||||||
|
update_verification_method(VERIFIED_BY_CERT);
|
||||||
|
status = EFI_SUCCESS;
|
||||||
|
return status;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ if (AuthenticodeVerify(cert->CertData,
|
||||||
|
+ cert->Hdr.dwLength - sizeof(cert->Hdr),
|
||||||
|
+ vendor_cert, vendor_cert_size,
|
||||||
|
+ sha1hash, SHA1_DIGEST_SIZE)) {
|
||||||
|
+ update_verification_method(VERIFIED_BY_CERT);
|
||||||
|
+ status = EFI_SUCCESS;
|
||||||
|
+ return status;
|
||||||
|
+ }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
--
|
||||||
|
2.7.5
|
||||||
|
|
||||||
@@ -0,0 +1,36 @@
|
|||||||
|
From 85e74fa95094175753e39acdd694f9c639069abf Mon Sep 17 00:00:00 2001
|
||||||
|
From: Lans Zhang <jia.zhang@windriver.com>
|
||||||
|
Date: Fri, 18 Mar 2016 12:30:08 +0800
|
||||||
|
Subject: [PATCH 05/11] Fix signing failure due to not finding certificate
|
||||||
|
|
||||||
|
Upstream-Status: Pending
|
||||||
|
|
||||||
|
The shim.p12 containing private sample key should be imported after
|
||||||
|
importing the corresponding certificate shim.crt. Otherwise, the
|
||||||
|
nick name of shim certificate cannot be used.
|
||||||
|
|
||||||
|
Signed-off-by: Lans Zhang <jia.zhang@windriver.com>
|
||||||
|
---
|
||||||
|
Makefile | 4 ++--
|
||||||
|
1 file changed, 2 insertions(+), 2 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/Makefile b/Makefile
|
||||||
|
index dcfa357..efab050 100644
|
||||||
|
--- a/Makefile
|
||||||
|
+++ b/Makefile
|
||||||
|
@@ -124,10 +124,10 @@ version.c : version.c.in
|
||||||
|
-e "s,@@COMMIT@@,$(shell if [ -d .git ] ; then git log -1 --pretty=format:%H ; elif [ -f commit ]; then cat commit ; else echo commit id not available; fi)," \
|
||||||
|
< version.c.in > version.c
|
||||||
|
|
||||||
|
-certdb/secmod.db: shim.crt
|
||||||
|
+certdb/secmod.db: shim.crt shim.p12
|
||||||
|
-mkdir certdb
|
||||||
|
- $(PK12UTIL) -d certdb/ -i shim.p12 -W "" -K ""
|
||||||
|
$(CERTUTIL) -d certdb/ -A -i shim.crt -n shim -t u
|
||||||
|
+ $(PK12UTIL) -d certdb/ -i shim.p12 -W "" -K ""
|
||||||
|
|
||||||
|
shim.o: $(SOURCES) shim_cert.h
|
||||||
|
shim.o: $(wildcard *.h)
|
||||||
|
--
|
||||||
|
2.11.0
|
||||||
|
|
||||||
@@ -0,0 +1,33 @@
|
|||||||
|
From 1f03018aa0b7df2eab576d410ec88e8cf66b06e0 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Lans Zhang <jia.zhang@windriver.com>
|
||||||
|
Date: Wed, 21 Sep 2016 11:25:14 +0800
|
||||||
|
Subject: [PATCH 06/11] Prevent from removing intermediate .efi
|
||||||
|
|
||||||
|
Upstream-Status: Pending
|
||||||
|
|
||||||
|
Otherwise Make will delete the .efi during the build:
|
||||||
|
sysroots/x86_64-linux/usr/bin/pesign -n certdb -i MokManager.efi -c "shim" -s -o MokManager.efi.signed -f
|
||||||
|
rm fallback.efi MokManager.efi
|
||||||
|
DEBUG: Shell function do_compile finished
|
||||||
|
|
||||||
|
Signed-off-by: Lans Zhang <jia.zhang@windriver.com>
|
||||||
|
---
|
||||||
|
Makefile | 2 ++
|
||||||
|
1 file changed, 2 insertions(+)
|
||||||
|
|
||||||
|
diff --git a/Makefile b/Makefile
|
||||||
|
index efab050..7c71993 100644
|
||||||
|
--- a/Makefile
|
||||||
|
+++ b/Makefile
|
||||||
|
@@ -100,6 +100,8 @@ MOK_SOURCES = MokManager.c shim.h include/console.h PasswordCrypt.c PasswordCryp
|
||||||
|
FALLBACK_OBJS = fallback.o
|
||||||
|
FALLBACK_SRCS = fallback.c
|
||||||
|
|
||||||
|
+.PRECIOUS: $(MMNAME).efi $(FBNAME).efi
|
||||||
|
+
|
||||||
|
ifneq ($(origin ENABLE_HTTPBOOT), undefined)
|
||||||
|
OBJS += httpboot.o
|
||||||
|
SOURCES += httpboot.c httpboot.h
|
||||||
|
--
|
||||||
|
2.11.0
|
||||||
|
|
||||||
@@ -0,0 +1,44 @@
|
|||||||
|
From 04da6c928d5f15b7adb6c51e55b9aa0a8126063d Mon Sep 17 00:00:00 2001
|
||||||
|
From: Lans Zhang <jia.zhang@windriver.com>
|
||||||
|
Date: Wed, 21 Sep 2016 11:31:02 +0800
|
||||||
|
Subject: [PATCH 07/11] Use sbsign to sign MokManager and fallback
|
||||||
|
|
||||||
|
Upstream-Status: Pending
|
||||||
|
|
||||||
|
pesign is written with -std=gnu11 and thus the host gcc version lower
|
||||||
|
than 4.7 cannot build out pesign.
|
||||||
|
|
||||||
|
sbsign is another alternate used to sign efi binary and it works well.
|
||||||
|
Therefore, drop to use sbsign to sign efi binary.
|
||||||
|
|
||||||
|
Signed-off-by: Lans Zhang <jia.zhang@windriver.com>
|
||||||
|
---
|
||||||
|
Makefile | 5 +++--
|
||||||
|
1 file changed, 3 insertions(+), 2 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/Makefile b/Makefile
|
||||||
|
index 7c71993..58b4b4c 100644
|
||||||
|
--- a/Makefile
|
||||||
|
+++ b/Makefile
|
||||||
|
@@ -12,6 +12,7 @@ HEXDUMP ?= hexdump
|
||||||
|
PK12UTIL ?= pk12util
|
||||||
|
CERTUTIL ?= certutil
|
||||||
|
PESIGN ?= pesign
|
||||||
|
+SBSIGN ?= sbsign
|
||||||
|
|
||||||
|
ARCH = $(shell $(CC) -dumpmachine | cut -f1 -d- | sed s,i[3456789]86,ia32,)
|
||||||
|
OBJCOPY_GTE224 = $(shell expr `$(OBJCOPY) --version |grep ^"GNU objcopy" | sed 's/^.*\((.*)\|version\) //g' | cut -f1-2 -d.` \>= 2.24)
|
||||||
|
@@ -190,8 +191,8 @@ endif
|
||||||
|
-j .note.gnu.build-id \
|
||||||
|
$(FORMAT) $^ $@.debug
|
||||||
|
|
||||||
|
-%.efi.signed: %.efi certdb/secmod.db
|
||||||
|
- $(PESIGN) -n certdb -i $< -c "shim" -s -o $@ -f
|
||||||
|
+%.efi.signed: %.efi shim.key shim.crt
|
||||||
|
+ $(SBSIGN) --key shim.key --cert shim.crt --output $@ $<
|
||||||
|
|
||||||
|
clean:
|
||||||
|
$(MAKE) -C Cryptlib clean
|
||||||
|
--
|
||||||
|
2.11.0
|
||||||
|
|
||||||
@@ -0,0 +1,35 @@
|
|||||||
|
From 508a31905aff2d271f1b82a5a36a614113b7fe85 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Lans Zhang <jia.zhang@windriver.com>
|
||||||
|
Date: Mon, 6 Jun 2016 16:28:09 +0800
|
||||||
|
Subject: [PATCH 08/11] Fix the world build failure due to the missing rule of
|
||||||
|
generating shim.key
|
||||||
|
|
||||||
|
Upstream-Status: Pending
|
||||||
|
|
||||||
|
shim.key is not given without feature/mok-secure-boot, the script
|
||||||
|
make-certs already integrated in shim is able to generate it and shim.crt
|
||||||
|
for signing. However, the commit 79c0d3ab3964ff03483277a515aaf50016bbe786
|
||||||
|
forgets to add the rule of generating shim.key, causing the world build
|
||||||
|
failure.
|
||||||
|
|
||||||
|
Signed-off-by: Lans Zhang <jia.zhang@windriver.com>
|
||||||
|
---
|
||||||
|
Makefile | 2 +-
|
||||||
|
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||||
|
|
||||||
|
diff --git a/Makefile b/Makefile
|
||||||
|
index 58b4b4c..0da5e6c 100644
|
||||||
|
--- a/Makefile
|
||||||
|
+++ b/Makefile
|
||||||
|
@@ -110,7 +110,7 @@ endif
|
||||||
|
|
||||||
|
all: $(TARGET)
|
||||||
|
|
||||||
|
-shim.crt:
|
||||||
|
+shim.crt shim.key:
|
||||||
|
./make-certs shim shim@xn--u4h.net all codesign 1.3.6.1.4.1.311.10.3.1 </dev/null
|
||||||
|
|
||||||
|
shim.cer: shim.crt
|
||||||
|
--
|
||||||
|
2.11.0
|
||||||
|
|
||||||
@@ -0,0 +1,35 @@
|
|||||||
|
From b3d57a092d837fe8134e0b3ff408040fa33d4efc Mon Sep 17 00:00:00 2001
|
||||||
|
From: Yunguo Wei <yunguo.wei@windriver.com>
|
||||||
|
Date: Wed, 28 Dec 2016 11:08:37 +0800
|
||||||
|
Subject: [PATCH 10/11] Makefile: do not sign the efi file
|
||||||
|
|
||||||
|
Shim tries to sign all the efi binaries at build time, but is not
|
||||||
|
suitable for us. Because the private key has to be supplied, and this
|
||||||
|
doesn't make sense to EDSS key.
|
||||||
|
|
||||||
|
We will use a seperated function in bitbake file to
|
||||||
|
sign these efi binaries, so that we can freely use EDSS key, Wind
|
||||||
|
River sample key or user key.
|
||||||
|
|
||||||
|
Signed-off-by: Yunguo Wei <yunguo.wei@windriver.com>
|
||||||
|
Signed-off-by: Lans Zhang <jia.zhang@windriver.com>
|
||||||
|
---
|
||||||
|
Makefile | 2 +-
|
||||||
|
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||||
|
|
||||||
|
diff --git a/Makefile b/Makefile
|
||||||
|
index 24e21a8..0912cd0 100644
|
||||||
|
--- a/Makefile
|
||||||
|
+++ b/Makefile
|
||||||
|
@@ -92,7 +92,7 @@ endif
|
||||||
|
|
||||||
|
LDFLAGS = --hash-style=sysv -nostdlib -znocombreloc -T $(EFI_LDS) -shared -Bsymbolic -L$(EFI_PATH) -L$(LIB_PATH) -LCryptlib -LCryptlib/OpenSSL $(EFI_CRT_OBJS) --build-id=sha1
|
||||||
|
|
||||||
|
-TARGET = $(SHIMNAME).efi $(MMNAME).efi.signed $(FBNAME).efi.signed
|
||||||
|
+TARGET = $(SHIMNAME).efi $(MMNAME).efi $(FBNAME).efi
|
||||||
|
OBJS = shim.o netboot.o cert.o replacements.o tpm.o version.o
|
||||||
|
KEYS = shim_cert.h ocsp.* ca.* shim.crt shim.csr shim.p12 shim.pem shim.key shim.cer
|
||||||
|
SOURCES = shim.c shim.h netboot.c include/PeImage.h include/wincert.h include/console.h replacements.c replacements.h tpm.c tpm.h version.c version.h
|
||||||
|
--
|
||||||
|
2.11.0
|
||||||
|
|
||||||
@@ -0,0 +1,69 @@
|
|||||||
|
From 62489adc36c5177f90ed16af936a4c0a992cea7e Mon Sep 17 00:00:00 2001
|
||||||
|
From: Lans Zhang <jia.zhang@windriver.com>
|
||||||
|
Date: Wed, 21 Sep 2016 11:17:29 +0800
|
||||||
|
Subject: [PATCH 11/11] Update verification_method if the loaded image is
|
||||||
|
signed by shim/vendor cert
|
||||||
|
|
||||||
|
Upstream-Status: Pending
|
||||||
|
|
||||||
|
Also, if the loaded image is not verfied by cert, the validation process
|
||||||
|
should be allowed as well.
|
||||||
|
|
||||||
|
Signed-off-by: Lans Zhang <jia.zhang@windriver.com>
|
||||||
|
---
|
||||||
|
replacements.c | 2 +-
|
||||||
|
shim.c | 4 ++++
|
||||||
|
2 files changed, 5 insertions(+), 1 deletion(-)
|
||||||
|
|
||||||
|
diff --git a/replacements.c b/replacements.c
|
||||||
|
index 01eda0e..9ed5a5d 100644
|
||||||
|
--- a/replacements.c
|
||||||
|
+++ b/replacements.c
|
||||||
|
@@ -144,7 +144,7 @@ start_image(EFI_HANDLE image_handle, UINTN *exit_data_size, CHAR16 **exit_data)
|
||||||
|
static EFI_STATUS EFIAPI
|
||||||
|
exit_boot_services(EFI_HANDLE image_key, UINTN map_key)
|
||||||
|
{
|
||||||
|
- if (loader_is_participating || verification_method == VERIFIED_BY_HASH) {
|
||||||
|
+ if (loader_is_participating || verification_method != VERIFIED_BY_NOTHING) {
|
||||||
|
unhook_system_services();
|
||||||
|
EFI_STATUS status;
|
||||||
|
status = systab->BootServices->ExitBootServices(image_key, map_key);
|
||||||
|
diff --git a/shim.c b/shim.c
|
||||||
|
index 364784b..ef62145 100644
|
||||||
|
--- a/shim.c
|
||||||
|
+++ b/shim.c
|
||||||
|
@@ -1029,6 +1029,7 @@ static EFI_STATUS verify_buffer (char *data, int datasize,
|
||||||
|
cert->Hdr.dwLength - sizeof(cert->Hdr),
|
||||||
|
shim_cert, sizeof(shim_cert), sha256hash,
|
||||||
|
SHA256_DIGEST_SIZE)) {
|
||||||
|
+ update_verification_method(VERIFIED_BY_CERT);
|
||||||
|
status = EFI_SUCCESS;
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
@@ -1037,6 +1038,7 @@ static EFI_STATUS verify_buffer (char *data, int datasize,
|
||||||
|
cert->Hdr.dwLength - sizeof(cert->Hdr),
|
||||||
|
shim_cert, sizeof(shim_cert), sha1hash,
|
||||||
|
SHA1_DIGEST_SIZE)) {
|
||||||
|
+ update_verification_method(VERIFIED_BY_CERT);
|
||||||
|
status = EFI_SUCCESS;
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
@@ -1050,6 +1052,7 @@ static EFI_STATUS verify_buffer (char *data, int datasize,
|
||||||
|
cert->Hdr.dwLength - sizeof(cert->Hdr),
|
||||||
|
vendor_cert, vendor_cert_size,
|
||||||
|
sha256hash, SHA256_DIGEST_SIZE)) {
|
||||||
|
+ update_verification_method(VERIFIED_BY_CERT);
|
||||||
|
status = EFI_SUCCESS;
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
@@ -1058,6 +1061,7 @@ static EFI_STATUS verify_buffer (char *data, int datasize,
|
||||||
|
cert->Hdr.dwLength - sizeof(cert->Hdr),
|
||||||
|
vendor_cert, vendor_cert_size,
|
||||||
|
sha1hash, SHA1_DIGEST_SIZE)) {
|
||||||
|
+ update_verification_method(VERIFIED_BY_CERT);
|
||||||
|
status = EFI_SUCCESS;
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
--
|
||||||
|
2.11.0
|
||||||
|
|
||||||
@@ -0,0 +1,28 @@
|
|||||||
|
From 1f22dc6be768b7032b73ea963901de270e3c99d9 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Lans Zhang <jia.zhang@windriver.com>
|
||||||
|
Date: Sun, 18 Jun 2017 21:50:26 +0800
|
||||||
|
Subject: [PATCH] netboot: replace the depreciated EFI_PXE_BASE_CODE
|
||||||
|
|
||||||
|
The newer gnu-efi already uses EFI_PXE_BASE_CODE_PROTOCOL instead.
|
||||||
|
|
||||||
|
Signed-off-by: Lans Zhang <jia.zhang@windriver.com>
|
||||||
|
---
|
||||||
|
netboot.c | 2 +-
|
||||||
|
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||||
|
|
||||||
|
diff --git a/netboot.c b/netboot.c
|
||||||
|
index 1cc1a2b..32c9b0a 100644
|
||||||
|
--- a/netboot.c
|
||||||
|
+++ b/netboot.c
|
||||||
|
@@ -43,7 +43,7 @@
|
||||||
|
#define ntohs(x) __builtin_bswap16(x) /* supported both by GCC and clang */
|
||||||
|
#define htons(x) ntohs(x)
|
||||||
|
|
||||||
|
-static EFI_PXE_BASE_CODE *pxe;
|
||||||
|
+static EFI_PXE_BASE_CODE_PROTOCOL *pxe;
|
||||||
|
static EFI_IP_ADDRESS tftp_addr;
|
||||||
|
static CHAR8 *full_path;
|
||||||
|
|
||||||
|
--
|
||||||
|
2.7.5
|
||||||
|
|
||||||
30
meta-efi-secure-boot/recipes-bsp/shim/shim/LICENSE
Normal file
30
meta-efi-secure-boot/recipes-bsp/shim/shim/LICENSE
Normal file
@@ -0,0 +1,30 @@
|
|||||||
|
Copyright 2012 Red Hat, Inc <mjg@redhat.com>
|
||||||
|
|
||||||
|
Redistribution and use in source and binary forms, with or without
|
||||||
|
modification, are permitted provided that the following conditions
|
||||||
|
are met:
|
||||||
|
|
||||||
|
Redistributions of source code must retain the above copyright
|
||||||
|
notice, this list of conditions and the following disclaimer.
|
||||||
|
|
||||||
|
Redistributions in binary form must reproduce the above copyright
|
||||||
|
notice, this list of conditions and the following disclaimer in the
|
||||||
|
documentation and/or other materials provided with the
|
||||||
|
distribution.
|
||||||
|
|
||||||
|
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||||
|
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||||
|
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||||
|
FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||||
|
COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
|
||||||
|
INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||||
|
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||||
|
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||||
|
HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
||||||
|
STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||||
|
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
|
||||||
|
OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
|
Significant portions of this code are derived from Tianocore
|
||||||
|
(http://tianocore.sf.net) and are Copyright 2009-2012 Intel
|
||||||
|
Corporation.
|
||||||
137
meta-efi-secure-boot/recipes-bsp/shim/shim_git.bb
Normal file
137
meta-efi-secure-boot/recipes-bsp/shim/shim_git.bb
Normal file
@@ -0,0 +1,137 @@
|
|||||||
|
SUMMARY = "shim is a trivial EFI application."
|
||||||
|
DESCRIPTION = "shim is a trivial EFI application that, when run, attempts to open and \
|
||||||
|
execute another application. It will initially attempt to do this via the \
|
||||||
|
standard EFI LoadImage() and StartImage() calls. If these fail (because secure \
|
||||||
|
boot is enabled and the binary is not signed with an appropriate key, for \
|
||||||
|
instance) it will then validate the binary against a built-in certificate. If \
|
||||||
|
this succeeds and if the binary or signing key are not blacklisted then shim \
|
||||||
|
will relocate and execute the binary."
|
||||||
|
HOMEPAGE = "https://github.com/rhinstaller/shim.git"
|
||||||
|
SECTION = "bootloaders"
|
||||||
|
|
||||||
|
LICENSE = "BSD-2-Clause"
|
||||||
|
LIC_FILES_CHKSUM = "file://COPYRIGHT;md5=b92e63892681ee4e8d27e7a7e87ef2bc"
|
||||||
|
PR = "r0"
|
||||||
|
|
||||||
|
COMPATIBLE_HOST = '(i.86|x86_64).*-linux'
|
||||||
|
|
||||||
|
inherit deploy user-key-store
|
||||||
|
|
||||||
|
SRC_URI = " \
|
||||||
|
git://github.com/rhinstaller/shim.git \
|
||||||
|
file://0001-shim-allow-to-verify-sha1-digest-for-Authenticode.patch \
|
||||||
|
file://0005-Fix-signing-failure-due-to-not-finding-certificate.patch;apply=0 \
|
||||||
|
file://0006-Prevent-from-removing-intermediate-.efi.patch \
|
||||||
|
file://0007-Use-sbsign-to-sign-MokManager-and-fallback.patch \
|
||||||
|
file://0008-Fix-the-world-build-failure-due-to-the-missing-rule-.patch \
|
||||||
|
file://0010-Makefile-do-not-sign-the-efi-file.patch \
|
||||||
|
file://0011-Update-verification_method-if-the-loaded-image-is-si.patch;apply=0 \
|
||||||
|
file://0012-netboot-replace-the-depreciated-EFI_PXE_BASE_CODE.patch \
|
||||||
|
"
|
||||||
|
SRC_URI_append_x86-64 = " \
|
||||||
|
${@bb.utils.contains('DISTRO_FEATURES', 'msft', 'file://shim${EFI_ARCH}.efi.signed file://LICENSE' if uks_signing_model(d) == 'sample' else '', '', d)} \
|
||||||
|
"
|
||||||
|
|
||||||
|
SRCREV = "55c65546e46a78edbe41e88cb4ccbd2522e09625"
|
||||||
|
PV = "12+git${SRCPV}"
|
||||||
|
|
||||||
|
S = "${WORKDIR}/git"
|
||||||
|
DEPENDS += "\
|
||||||
|
gnu-efi nss openssl util-linux-native openssl-native nss-native \
|
||||||
|
"
|
||||||
|
|
||||||
|
EFI_ARCH_x86 = "ia32"
|
||||||
|
EFI_ARCH_x86-64 = "x64"
|
||||||
|
|
||||||
|
EXTRA_OEMAKE = " \
|
||||||
|
CROSS_COMPILE="${TARGET_PREFIX}" \
|
||||||
|
LIB_GCC="`${CC} -print-libgcc-file-name`" \
|
||||||
|
LIB_PATH="${STAGING_LIBDIR}" \
|
||||||
|
EFI_PATH="${STAGING_LIBDIR}" \
|
||||||
|
EFI_INCLUDE="${STAGING_INCDIR}/efi" \
|
||||||
|
RELEASE="_${DISTRO}_${DISTRO_VERSION}" \
|
||||||
|
DEFAULT_LOADER=\\\\\\SELoader${EFI_ARCH}.efi \
|
||||||
|
OPENSSL=${STAGING_BINDIR_NATIVE}/openssl \
|
||||||
|
HEXDUMP=${STAGING_BINDIR_NATIVE}/hexdump \
|
||||||
|
PK12UTIL=${STAGING_BINDIR_NATIVE}/pk12util \
|
||||||
|
CERTUTIL=${STAGING_BINDIR_NATIVE}/certutil \
|
||||||
|
SBSIGN=${STAGING_BINDIR_NATIVE}/sbsign \
|
||||||
|
AR=${AR} \
|
||||||
|
${@'VENDOR_CERT_FILE=${WORKDIR}/vendor_cert.cer' if d.getVar('MOK_SB', True) == '1' else ''} \
|
||||||
|
${@'VENDOR_DBX_FILE=${WORKDIR}/vendor_dbx.esl' if uks_signing_model(d) == 'user' else ''} \
|
||||||
|
"
|
||||||
|
|
||||||
|
PARALLEL_MAKE = ""
|
||||||
|
|
||||||
|
EFI_TARGET = "/boot/efi/EFI/BOOT"
|
||||||
|
FILES_${PN} += "${EFI_TARGET}"
|
||||||
|
|
||||||
|
MSFT = "${@bb.utils.contains('DISTRO_FEATURES', 'msft', '1', '0', d)}"
|
||||||
|
|
||||||
|
# Prepare the signing certificate and keys
|
||||||
|
python do_prepare_signing_keys() {
|
||||||
|
# For UEFI_SB, shim is not built
|
||||||
|
if d.getVar('MOK_SB', True) != '1':
|
||||||
|
return
|
||||||
|
|
||||||
|
path = create_mok_vendor_dbx(d)
|
||||||
|
|
||||||
|
# Prepare shim_cert and vendor_cert.
|
||||||
|
dir = mok_sb_keys_dir(d)
|
||||||
|
|
||||||
|
import shutil
|
||||||
|
|
||||||
|
shutil.copyfile(dir + 'shim_cert.pem', d.getVar('S', True) + '/shim.crt')
|
||||||
|
pem2der(dir + 'vendor_cert.pem', d.getVar('WORKDIR', True) + '/vendor_cert.cer', d)
|
||||||
|
|
||||||
|
# Replace the shim certificate with EV certificate for speeding up
|
||||||
|
# the progress of MSFT signing.
|
||||||
|
if d.expand('${MSFT}') == "1" and uks_signing_model(d) == "sample":
|
||||||
|
shutil.copyfile(d.expand('${EV_CERT}'), d.expand('${S}/shim.crt'))
|
||||||
|
}
|
||||||
|
addtask prepare_signing_keys after do_configure before do_compile
|
||||||
|
|
||||||
|
python do_sign() {
|
||||||
|
# The pre-signed shim binary will override the one built from the
|
||||||
|
# scratch.
|
||||||
|
pre_signed = d.expand('${WORKDIR}/shim${EFI_ARCH}.efi.signed')
|
||||||
|
dst = d.expand('${B}/shim${EFI_ARCH}.efi.signed')
|
||||||
|
if d.expand('${MSFT}') == "1" and os.path.exists(pre_signed):
|
||||||
|
import shutil
|
||||||
|
shutil.copyfile(pre_signed, dst)
|
||||||
|
else:
|
||||||
|
if uks_signing_model(d) in ('sample', 'user'):
|
||||||
|
uefi_sb_sign(d.expand('${S}/shim${EFI_ARCH}.efi'), dst, d)
|
||||||
|
elif uks_signing_model(d) == 'edss':
|
||||||
|
edss_sign_efi_image(d.expand('${S}/shim${EFI_ARCH}.efi'), dst, d)
|
||||||
|
|
||||||
|
sb_sign(d.expand('${S}/mm${EFI_ARCH}.efi'), d.expand('${B}/mm${EFI_ARCH}.efi.signed'), d)
|
||||||
|
sb_sign(d.expand('${S}/fb${EFI_ARCH}.efi'), d.expand('${B}/fb${EFI_ARCH}.efi.signed'), d)
|
||||||
|
}
|
||||||
|
addtask sign after do_compile before do_install
|
||||||
|
|
||||||
|
do_install() {
|
||||||
|
install -d ${D}${EFI_TARGET}
|
||||||
|
|
||||||
|
local shim_dst="${D}${EFI_TARGET}/boot${EFI_ARCH}.efi"
|
||||||
|
local mm_dst="${D}${EFI_TARGET}/mm${EFI_ARCH}.efi"
|
||||||
|
if [ x"${UEFI_SB}" = x"1" ]; then
|
||||||
|
install -m 0600 ${B}/shim${EFI_ARCH}.efi.signed $shim_dst
|
||||||
|
install -m 0600 ${B}/mm${EFI_ARCH}.efi.signed $mm_dst
|
||||||
|
else
|
||||||
|
install -m 0600 ${B}/shim${EFI_ARCH}.efi $shim_dst
|
||||||
|
install -m 0600 ${B}/mm${EFI_ARCH}.efi $mm_dst
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
# Install the unsigned images for manual signing
|
||||||
|
do_deploy() {
|
||||||
|
install -d ${DEPLOYDIR}/efi-unsigned
|
||||||
|
|
||||||
|
install -m 0600 ${B}/shim${EFI_ARCH}.efi ${DEPLOYDIR}/efi-unsigned/boot${EFI_ARCH}.efi
|
||||||
|
install -m 0600 ${B}/mm${EFI_ARCH}.efi ${DEPLOYDIR}/efi-unsigned/mm${EFI_ARCH}.efi
|
||||||
|
|
||||||
|
install -m 0600 "${D}${EFI_TARGET}/boot${EFI_ARCH}.efi" "${DEPLOYDIR}"
|
||||||
|
install -m 0600 "${D}${EFI_TARGET}/mm${EFI_ARCH}.efi" "${DEPLOYDIR}"
|
||||||
|
}
|
||||||
|
addtask deploy after do_install before do_build
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
DEPENDS += " \
|
||||||
|
${@bb.utils.contains('MACHINE_FEATURES', 'efi', 'gnu-efi', '', d)} \
|
||||||
|
"
|
||||||
|
|
||||||
|
EXTRA_OECONF += " \
|
||||||
|
${@bb.utils.contains('MACHINE_FEATURES', 'efi', '--enable-efi --enable-gnuefi --with-efi-libdir=${STAGING_LIBDIR} --with-efi-ldsdir=${STAGING_LIBDIR} --with-efi-includedir=${STAGING_INCDIR}', '', d)} \
|
||||||
|
"
|
||||||
48
meta-efi-secure-boot/recipes-devtools/libsign/libsign_git.bb
Normal file
48
meta-efi-secure-boot/recipes-devtools/libsign/libsign_git.bb
Normal file
@@ -0,0 +1,48 @@
|
|||||||
|
SUMMARY = "A generic signing tool framework"
|
||||||
|
DESCRIPTION = " \
|
||||||
|
This project targets to provide a generic signing framework. This framework \
|
||||||
|
separates the signing request and signing process and correspondingly forms \
|
||||||
|
the so-called signlet and signaturelet. \
|
||||||
|
Each signaturelet only concerns about the details about how to construct the \
|
||||||
|
layout of a signature format, and signlet only cares how to construct the \
|
||||||
|
signing request. \
|
||||||
|
"
|
||||||
|
SECTION = "devel"
|
||||||
|
LICENSE = "BSD-3-Clause"
|
||||||
|
LIC_FILES_CHKSUM = "file://${S}/LICENSE;md5=d9bf404642f21afb4ad89f95d7bc91ee"
|
||||||
|
|
||||||
|
SRC_URI = " \
|
||||||
|
git://github.com/jiazhang0/libsign.git \
|
||||||
|
"
|
||||||
|
SRCREV = "dfab84b4235a36bb395bc6663e50578bb2f9edca"
|
||||||
|
PV = "0.3.2+git${SRCPV}"
|
||||||
|
|
||||||
|
DEPENDS += "openssl"
|
||||||
|
RDEPENDS_${PN}_class-target += "libcrypto"
|
||||||
|
RDEPENDS_${PN}_class-native += "openssl"
|
||||||
|
|
||||||
|
PARALLEL_MAKE = ""
|
||||||
|
|
||||||
|
S = "${WORKDIR}/git"
|
||||||
|
|
||||||
|
EXTRA_OEMAKE = " \
|
||||||
|
CC="${CC}" \
|
||||||
|
bindir="${STAGING_BINDIR}" \
|
||||||
|
libdir="${STAGING_LIBDIR}" \
|
||||||
|
includedir="${STAGING_INCDIR}" \
|
||||||
|
EXTRA_CFLAGS="${CFLAGS}" \
|
||||||
|
EXTRA_LDFLAGS="${LDFLAGS}" \
|
||||||
|
SIGNATURELET_DIR="${libdir}/signaturelet" \
|
||||||
|
BINDIR="${bindir}" \
|
||||||
|
LIBDIR="${libdir}" \
|
||||||
|
"
|
||||||
|
|
||||||
|
do_install() {
|
||||||
|
oe_runmake install DESTDIR="${D}"
|
||||||
|
}
|
||||||
|
|
||||||
|
FILES_${PN} += " \
|
||||||
|
${libdir}/signaturelet \
|
||||||
|
"
|
||||||
|
|
||||||
|
BBCLASSEXTEND = "native"
|
||||||
@@ -0,0 +1,50 @@
|
|||||||
|
SUMMARY = "Signing utility for UEFI secure boot"
|
||||||
|
|
||||||
|
LICENSE = "GPLv3"
|
||||||
|
LIC_FILES_CHKSUM = "file://LICENSE.GPLv3;md5=9eef91148a9b14ec7f9df333daebc746"
|
||||||
|
|
||||||
|
SRC_URI = "git://kernel.ubuntu.com/jk/sbsigntool \
|
||||||
|
file://ccan.git.tar.bz2 \
|
||||||
|
file://disable-man-page-creation.patch \
|
||||||
|
file://Fix-for-multi-sign.patch \
|
||||||
|
file://sbsign-add-x-option-to-avoid-overwrite-existing-sign.patch \
|
||||||
|
file://fix-mixed-implicit-and-normal-rules.patch;apply=0 \
|
||||||
|
file://image-fix-the-segment-fault-caused-by-the-uninitiali.patch \
|
||||||
|
"
|
||||||
|
|
||||||
|
SRCREV="951ee95a301674c046f55330cd7460e1314deff2"
|
||||||
|
PV = "0.6+git${SRCPV}"
|
||||||
|
|
||||||
|
inherit autotools-brokensep pkgconfig native
|
||||||
|
|
||||||
|
DEPENDS_append = " binutils-native openssl-native gnu-efi-native util-linux-native"
|
||||||
|
|
||||||
|
S = "${WORKDIR}/git"
|
||||||
|
|
||||||
|
do_configure() {
|
||||||
|
cd ${S}
|
||||||
|
rm -rf lib/ccan.git
|
||||||
|
git clone ${WORKDIR}/ccan.git lib/ccan.git
|
||||||
|
cd lib/ccan.git && git apply ${WORKDIR}/fix-mixed-implicit-and-normal-rules.patch && cd -
|
||||||
|
|
||||||
|
OLD_CC="${CC}"
|
||||||
|
|
||||||
|
if [ ! -e lib/ccan ]; then
|
||||||
|
export CC="${BUILD_CC}"
|
||||||
|
export TMPDIR=${B}
|
||||||
|
lib/ccan.git/tools/create-ccan-tree \
|
||||||
|
--build-type=automake lib/ccan \
|
||||||
|
talloc read_write_all build_assert array_size || exit 2
|
||||||
|
fi
|
||||||
|
|
||||||
|
export CC="${OLD_CC}"
|
||||||
|
./autogen.sh --noconfigure
|
||||||
|
oe_runconf
|
||||||
|
}
|
||||||
|
|
||||||
|
EXTRA_OEMAKE += " \
|
||||||
|
INCLUDES='-I../lib/ccan.git/' \
|
||||||
|
EFI_CPPFLAGS='-DEFI_FUNCTION_WRAPPER \
|
||||||
|
-I${STAGING_INCDIR}/efi \
|
||||||
|
-I${STAGING_INCDIR}/efi/${BUILD_ARCH}' \
|
||||||
|
"
|
||||||
@@ -0,0 +1,41 @@
|
|||||||
|
From e58a528ef57e53008222f238cce7c326a14572e2 Mon Sep 17 00:00:00 2001
|
||||||
|
From: James Bottomley <JBottomley@Parallels.com>
|
||||||
|
Date: Mon, 30 Sep 2013 19:25:37 -0700
|
||||||
|
Subject: [PATCH] Fix for multi-sign
|
||||||
|
|
||||||
|
Upstream-Status: Inappropriate [embedded specific]
|
||||||
|
|
||||||
|
The new Tianocore multi-sign code fails now for images signed with
|
||||||
|
sbsigntools. The reason is that we don't actually align the signature table,
|
||||||
|
we just slap it straight after the binary data. Unfortunately, the new
|
||||||
|
multi-signature code checks that our alignment offsets are correct and fails
|
||||||
|
the signature for this reason. Fix by adding junk to the end of the image to
|
||||||
|
align the signature section.
|
||||||
|
|
||||||
|
Signed-off-by: James Bottomley <JBottomley@Parallels.com>
|
||||||
|
---
|
||||||
|
src/image.c | 8 +++++++-
|
||||||
|
1 file changed, 7 insertions(+), 1 deletion(-)
|
||||||
|
|
||||||
|
diff --git a/src/image.c b/src/image.c
|
||||||
|
index 10eba0e..519e288 100644
|
||||||
|
--- a/src/image.c
|
||||||
|
+++ b/src/image.c
|
||||||
|
@@ -385,7 +385,13 @@ static int image_find_regions(struct image *image)
|
||||||
|
|
||||||
|
/* record the size of non-signature data */
|
||||||
|
r = &image->checksum_regions[image->n_checksum_regions - 1];
|
||||||
|
- image->data_size = (r->data - (void *)image->buf) + r->size;
|
||||||
|
+ /*
|
||||||
|
+ * The new Tianocore multisign does a stricter check of the signatures
|
||||||
|
+ * in particular, the signature table must start at an aligned offset
|
||||||
|
+ * fix this by adding bytes to the end of the text section (which must
|
||||||
|
+ * be included in the hash)
|
||||||
|
+ */
|
||||||
|
+ image->data_size = align_up((r->data - (void *)image->buf) + r->size, 8);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
--
|
||||||
|
1.8.4
|
||||||
|
|
||||||
Binary file not shown.
@@ -0,0 +1,15 @@
|
|||||||
|
Upstream-Status: Inappropriate [embedded specific]
|
||||||
|
|
||||||
|
diff --git a/docs/Makefile.am b/docs/Makefile.am
|
||||||
|
index 1b5a588..6918dd8 100644
|
||||||
|
--- a/docs/Makefile.am
|
||||||
|
+++ b/docs/Makefile.am
|
||||||
|
@@ -1,8 +1,4 @@
|
||||||
|
|
||||||
|
-man1_MANS = sbsign.1 sbverify.1 sbattach.1 sbvarsign.1 sbsiglist.1
|
||||||
|
-
|
||||||
|
-EXTRA_DIST = sbsign.1.in sbverify.1.in sbattach.1.in \
|
||||||
|
- sbvarsign.1.in sbsiglist.1.in
|
||||||
|
CLEANFILES = $(man1_MANS)
|
||||||
|
|
||||||
|
$(builddir)/%.1: $(srcdir)/%.1.in $(top_builddir)/src/%
|
||||||
@@ -0,0 +1,33 @@
|
|||||||
|
From 05e73dbe1f25600ad0dbb36b2d690560c5a36281 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Lans Zhang <jia.zhang@windriver.com>
|
||||||
|
Date: Tue, 31 Mar 2015 15:34:38 +0800
|
||||||
|
Subject: [PATCH] Fix mixed implicit and normal rules
|
||||||
|
|
||||||
|
Upstream-Status: Inappropriate [embedded specific]
|
||||||
|
|
||||||
|
This patch comes from upstream:
|
||||||
|
http://git.yoctoproject.org/cgit/cgit.cgi/meta-luv/plain/recipes-devtools/sbsigntool/sbsigntool/fix-mixed-implicit-and-normal-rules.patch
|
||||||
|
|
||||||
|
Signed-off-by: Lans Zhang <jia.zhang@windriver.com>
|
||||||
|
---
|
||||||
|
Makefile | 4 ----
|
||||||
|
1 file changed, 4 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/Makefile b/Makefile
|
||||||
|
index 65d0d8f..a83185d 100644
|
||||||
|
--- a/Makefile
|
||||||
|
+++ b/Makefile
|
||||||
|
@@ -39,10 +39,6 @@ $(SCOREDIR)/SUMMARY: $(MODS:%=$(SCOREDIR)/%.score)
|
||||||
|
$(CC) -v >> $@
|
||||||
|
cat $^ | grep 'Total score:' >> $@
|
||||||
|
|
||||||
|
-$(SCOREDIR)/%.score: ccan/%/_info tools/ccanlint/ccanlint $(OBJFILES)
|
||||||
|
- mkdir -p `dirname $@`
|
||||||
|
- $(CCANLINT) -v -s ccan/$* > $@ || true
|
||||||
|
-
|
||||||
|
$(ALL_DEPENDS): %/.depends: %/_info tools/ccan_depends
|
||||||
|
tools/ccan_depends $* > $@ || ( rm -f $@; exit 1 )
|
||||||
|
|
||||||
|
--
|
||||||
|
1.8.3.1
|
||||||
|
|
||||||
@@ -0,0 +1,30 @@
|
|||||||
|
From a6862cb3bb3b00a1d6704b2bd1fedbd1374be861 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Lans Zhang <jia.zhang@windriver.com>
|
||||||
|
Date: Thu, 6 Apr 2017 11:11:14 +0800
|
||||||
|
Subject: [PATCH] image: fix the segment fault caused by the uninitialized
|
||||||
|
sigbuf
|
||||||
|
|
||||||
|
The uninitialized struct image might contain a non-zeroed sigbuf and then
|
||||||
|
it is wrongly freed by image_add_signature().
|
||||||
|
|
||||||
|
Signed-off-by: Lans Zhang <jia.zhang@windriver.com>
|
||||||
|
---
|
||||||
|
src/image.c | 2 +-
|
||||||
|
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||||
|
|
||||||
|
diff --git a/src/image.c b/src/image.c
|
||||||
|
index cc55791..644e8f1 100644
|
||||||
|
--- a/src/image.c
|
||||||
|
+++ b/src/image.c
|
||||||
|
@@ -395,7 +395,7 @@ struct image *image_load(const char *filename)
|
||||||
|
struct image *image;
|
||||||
|
int rc;
|
||||||
|
|
||||||
|
- image = talloc(NULL, struct image);
|
||||||
|
+ image = talloc_zero(NULL, struct image);
|
||||||
|
if (!image) {
|
||||||
|
perror("talloc(image)");
|
||||||
|
return NULL;
|
||||||
|
--
|
||||||
|
2.11.0
|
||||||
|
|
||||||
@@ -0,0 +1,75 @@
|
|||||||
|
From 0016a571a5ea1ab65817973f179800947e1aa8de Mon Sep 17 00:00:00 2001
|
||||||
|
From: Lans Zhang <jia.zhang@windriver.com>
|
||||||
|
Date: Fri, 15 Jan 2016 09:40:56 +0800
|
||||||
|
Subject: [PATCH] sbsign: add -x option to avoid overwrite existing signature
|
||||||
|
|
||||||
|
Upstream-Status: Pending
|
||||||
|
|
||||||
|
Signed-off-by: Lans Zhang <jia.zhang@windriver.com>
|
||||||
|
---
|
||||||
|
src/sbsign.c | 17 +++++++++++++++--
|
||||||
|
1 file changed, 15 insertions(+), 2 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/src/sbsign.c b/src/sbsign.c
|
||||||
|
index dcf6eed..7dc101f 100644
|
||||||
|
--- a/src/sbsign.c
|
||||||
|
+++ b/src/sbsign.c
|
||||||
|
@@ -66,6 +66,7 @@ struct sign_context {
|
||||||
|
};
|
||||||
|
|
||||||
|
static struct option options[] = {
|
||||||
|
+ { "noresign", no_argument, NULL, 'x' },
|
||||||
|
{ "output", required_argument, NULL, 'o' },
|
||||||
|
{ "cert", required_argument, NULL, 'c' },
|
||||||
|
{ "key", required_argument, NULL, 'k' },
|
||||||
|
@@ -87,6 +88,7 @@ static void usage(void)
|
||||||
|
"\t--cert <certfile> certificate (x509 certificate)\n"
|
||||||
|
"\t--detached write a detached signature, instead of\n"
|
||||||
|
"\t a signed binary\n"
|
||||||
|
+ "\t--noresign don't re-sign the binary if signed\n"
|
||||||
|
"\t--output <file> write signed data to <file>\n"
|
||||||
|
"\t (default <efi-boot-image>.signed,\n"
|
||||||
|
"\t or <efi-boot-image>.pk7 for detached\n"
|
||||||
|
@@ -114,7 +116,7 @@ int main(int argc, char **argv)
|
||||||
|
const char *keyfilename, *certfilename;
|
||||||
|
struct sign_context *ctx;
|
||||||
|
uint8_t *buf, *tmp;
|
||||||
|
- int rc, c, sigsize;
|
||||||
|
+ int rc, c, sigsize, no_resign = 0;
|
||||||
|
|
||||||
|
ctx = talloc_zero(NULL, struct sign_context);
|
||||||
|
|
||||||
|
@@ -123,11 +125,14 @@ int main(int argc, char **argv)
|
||||||
|
|
||||||
|
for (;;) {
|
||||||
|
int idx;
|
||||||
|
- c = getopt_long(argc, argv, "o:c:k:dvVh", options, &idx);
|
||||||
|
+ c = getopt_long(argc, argv, "xo:c:k:dvVh", options, &idx);
|
||||||
|
if (c == -1)
|
||||||
|
break;
|
||||||
|
|
||||||
|
switch (c) {
|
||||||
|
+ case 'x':
|
||||||
|
+ no_resign = 1;
|
||||||
|
+ break;
|
||||||
|
case 'o':
|
||||||
|
ctx->outfilename = talloc_strdup(ctx, optarg);
|
||||||
|
break;
|
||||||
|
@@ -178,6 +183,14 @@ int main(int argc, char **argv)
|
||||||
|
if (!ctx->image)
|
||||||
|
return EXIT_FAILURE;
|
||||||
|
|
||||||
|
+ if (ctx->image->cert_table) {
|
||||||
|
+ if (no_resign) {
|
||||||
|
+ fprintf(stderr,
|
||||||
|
+ "Don't overwrite existing signature\n");
|
||||||
|
+ return EXIT_SUCCESS;
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
talloc_steal(ctx, ctx->image);
|
||||||
|
|
||||||
|
ERR_load_crypto_strings();
|
||||||
|
--
|
||||||
|
1.9.1
|
||||||
|
|
||||||
24
meta-efi-secure-boot/recipes-extended/mokutil/mokutil_git.bb
Normal file
24
meta-efi-secure-boot/recipes-extended/mokutil/mokutil_git.bb
Normal file
@@ -0,0 +1,24 @@
|
|||||||
|
SUMMARY = "The utility to manipulate machines owner keys which managed in shim"
|
||||||
|
|
||||||
|
LICENSE = "GPLv3"
|
||||||
|
LIC_FILES_CHKSUM = "file://COPYING;md5=d32239bcb673463ab874e80d47fae504"
|
||||||
|
|
||||||
|
SRC_URI = "\
|
||||||
|
git://github.com/lcp/mokutil.git \
|
||||||
|
"
|
||||||
|
|
||||||
|
S = "${WORKDIR}/git"
|
||||||
|
SRCREV = "e19adc575c1f9d8f08b7fbc594a0887ace63f83f"
|
||||||
|
PV = "0.3.0+git${SRCPV}"
|
||||||
|
|
||||||
|
inherit autotools pkgconfig
|
||||||
|
|
||||||
|
DEPENDS += "openssl efivar"
|
||||||
|
RDEPENDS_${PN} += "openssl efivar"
|
||||||
|
|
||||||
|
EXTRA_OEMAKE += "\
|
||||||
|
EFIVAR_LIBS='-L${STAGING_LIBDIR} -lefivar' \
|
||||||
|
OPENSSL_LIBS='-L${STAGING_LIBDIR} -lssl -lcrypto' \
|
||||||
|
"
|
||||||
|
|
||||||
|
FILES_${PN} += "${datadir}/bash-completion/*"
|
||||||
@@ -0,0 +1,101 @@
|
|||||||
|
FILESEXTRAPATHS_prepend := "${THISDIR}/linux-yocto:"
|
||||||
|
|
||||||
|
sccs = " \
|
||||||
|
${@bb.utils.contains('DISTRO_FEATURES', 'efi-secure-boot', \
|
||||||
|
'cfg/efi-ext.scc', '', d)} \
|
||||||
|
"
|
||||||
|
KERNEL_FEATURES_append_x86 += "${sccs}"
|
||||||
|
KERNEL_FEATURES_append_x86-64 += "${sccs}"
|
||||||
|
|
||||||
|
inherit user-key-store
|
||||||
|
|
||||||
|
fakeroot python do_sign() {
|
||||||
|
import re
|
||||||
|
|
||||||
|
if (d.expand('${TARGET_ARCH}') != 'x86_64') and (not re.match('i.86', d.expand('${TARGET_ARCH}'))):
|
||||||
|
return
|
||||||
|
|
||||||
|
if d.expand('${UEFI_SB}') != '1':
|
||||||
|
return
|
||||||
|
|
||||||
|
import shutil
|
||||||
|
|
||||||
|
for type in d.expand('${KERNEL_IMAGETYPES}').split():
|
||||||
|
kernel = d.expand('${B}/${KERNEL_OUTPUT_DIR}/') + type
|
||||||
|
|
||||||
|
# Prepare the unsigned kernel image for manual signing.
|
||||||
|
shutil.copy(kernel, d.expand('${B}/') + type + '.unsigned')
|
||||||
|
|
||||||
|
# SELoader signature is always based on the unsigned kernel image,
|
||||||
|
# disallowing chainloader to kernel efi-stub.
|
||||||
|
uks_sel_sign(kernel, d)
|
||||||
|
|
||||||
|
shutil.copyfile(kernel, d.expand('${D}/boot/') + type + d.expand('-${KERNEL_RELEASE}'))
|
||||||
|
shutil.copyfile(kernel + '.p7b', d.expand('${D}/boot/') + type + d.expand('-${KERNEL_RELEASE}.p7b'))
|
||||||
|
}
|
||||||
|
|
||||||
|
# Make sure the kernel image has been signed before kernel_do_deploy()
|
||||||
|
# which prepares the kernel image for creating usb/iso.
|
||||||
|
addtask sign after do_install before do_package do_populate_sysroot do_deploy
|
||||||
|
|
||||||
|
fakeroot python do_sign_bundled_kernel() {
|
||||||
|
import re
|
||||||
|
|
||||||
|
if (d.expand('${TARGET_ARCH}') != 'x86_64') and (not re.match('i.86', d.expand('${TARGET_ARCH}'))):
|
||||||
|
return
|
||||||
|
|
||||||
|
if d.expand('${UEFI_SB}') != '1':
|
||||||
|
return
|
||||||
|
|
||||||
|
if (d.expand('${INITRAMFS_IMAGE}') == '') or (d.expand('${INITRAMFS_IMAGE_BUNDLE}') != '1'):
|
||||||
|
return
|
||||||
|
|
||||||
|
import shutil
|
||||||
|
|
||||||
|
for type in d.expand('${KERNEL_IMAGETYPES}').split():
|
||||||
|
kernel = d.expand('${B}/${KERNEL_OUTPUT_DIR}/') + type + '.initramfs'
|
||||||
|
|
||||||
|
# Prepare the unsigned kernel image for manual signing.
|
||||||
|
shutil.copy(kernel, d.expand('${B}/') + type + '.initramfs.unsigned')
|
||||||
|
|
||||||
|
# SELoader signature is always based on the unsigned kernel image,
|
||||||
|
# disallowing chainloader to kernel efi-stub.
|
||||||
|
uks_sel_sign(kernel, d)
|
||||||
|
|
||||||
|
shutil.copyfile(kernel, d.expand('${D}/boot/') + type + d.expand('-initramfs-${MACHINE}.bin'))
|
||||||
|
shutil.copyfile(kernel + '.p7b', d.expand('${D}/boot/') + type + d.expand('-initramfs-${MACHINE}.bin.p7b'))
|
||||||
|
}
|
||||||
|
addtask sign_bundled_kernel after do_bundle_initramfs before do_deploy
|
||||||
|
|
||||||
|
do_deploy_append() {
|
||||||
|
install -d "${DEPLOYDIR}/efi-unsigned"
|
||||||
|
|
||||||
|
for type in ${KERNEL_IMAGETYPES}; do
|
||||||
|
if [ -f "${B}/$type.unsigned" ]; then
|
||||||
|
install -m 0644 "${B}/$type.unsigned" "${DEPLOYDIR}/efi-unsigned/$type"
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ -f "${B}/$type.initramfs.unsigned" ]; then
|
||||||
|
install -m 0644 "${B}/$type.initramfs.unsigned" "${DEPLOYDIR}/efi-unsigned/type.initramfs"
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ -f "${D}/boot/$type-initramfs-${MACHINE}.bin.p7b" ]; then
|
||||||
|
install -m 0644 "${D}/boot/$type-initramfs-${MACHINE}.bin.p7b" "${DEPLOYDIR}"
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ -f "${B}/${KERNEL_OUTPUT_DIR}/$type.p7b" ]; then
|
||||||
|
base_name="${type}-${KERNEL_IMAGE_BASE_NAME}.bin.p7b"
|
||||||
|
|
||||||
|
install -m 0644 "${B}/${KERNEL_OUTPUT_DIR}/$type.p7b" "${DEPLOYDIR}/$base_name"
|
||||||
|
ln -sf "$base_name" "${DEPLOYDIR}/$type-${KERNEL_IMAGE_SYMLINK_NAME}.bin.p7b"
|
||||||
|
ln -sf "$base_name" "${DEPLOYDIR}/$type.p7b"
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
}
|
||||||
|
|
||||||
|
# Ship *.p7b files to related packages
|
||||||
|
python do_package_prepend() {
|
||||||
|
for type in d.expand('${KERNEL_IMAGETYPES}').split():
|
||||||
|
typelower = type.lower()
|
||||||
|
d.appendVar('FILES_kernel-image-' + typelower, ' /boot/' + type + d.expand('-${KERNEL_VERSION_NAME}.p7b'))
|
||||||
|
}
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
require linux-yocto-efi-secure-boot.inc
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
require linux-yocto-efi-secure-boot.inc
|
||||||
@@ -0,0 +1,15 @@
|
|||||||
|
DESCRIPTION = "Slurp entire files into variables."
|
||||||
|
SECTION = "libs"
|
||||||
|
LICENSE = "Artistic-1.0 | GPL-1.0+"
|
||||||
|
|
||||||
|
LIC_FILES_CHKSUM = "file://README;beginline=37;endline=41;md5=255fbd5f98a90d51d9908d31271ae4d4"
|
||||||
|
SRC_URI = "http://search.cpan.org/CPAN/authors/id/U/UR/URI/File-Slurp-9999.19.tar.gz"
|
||||||
|
|
||||||
|
S = "${WORKDIR}/File-Slurp-${PV}"
|
||||||
|
|
||||||
|
inherit cpan
|
||||||
|
BBCLASSEXTEND="native"
|
||||||
|
PACKAGE_ARCH = "all"
|
||||||
|
|
||||||
|
SRC_URI[md5sum] = "7d584cd15c4f8b9547765eff8c4ef078"
|
||||||
|
SRC_URI[sha256sum] = "ce29ebe995097ebd6e9bc03284714cdfa0c46dc94f6b14a56980747ea3253643"
|
||||||
@@ -0,0 +1,44 @@
|
|||||||
|
From 7078852e4a89f5ba27e7a70bc69641e01a6bff7a Mon Sep 17 00:00:00 2001
|
||||||
|
From: Yunguo Wei <yunguo.wei@windriver.com>
|
||||||
|
Date: Thu, 19 Jan 2017 15:11:25 +0800
|
||||||
|
Subject: [PATCH] Remove use of deprecated readdir_r
|
||||||
|
|
||||||
|
Backport 1dc6d576fa4(Remove use of deprecated readdir_r) from
|
||||||
|
https://github.com/rhinstaller/efivar.git
|
||||||
|
|
||||||
|
Signed-off-by: Yunguo Wei <yunguo.wei@windriver.com>
|
||||||
|
---
|
||||||
|
src/vars.c | 12 ++++--------
|
||||||
|
1 file changed, 4 insertions(+), 8 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/src/vars.c b/src/vars.c
|
||||||
|
index 2a276de..ec0d6bf 100644
|
||||||
|
--- a/src/vars.c
|
||||||
|
+++ b/src/vars.c
|
||||||
|
@@ -126,19 +126,15 @@ is_64bit(void)
|
||||||
|
if (dfd < 0)
|
||||||
|
goto err;
|
||||||
|
|
||||||
|
- struct dirent entry;
|
||||||
|
- struct dirent *result = NULL;
|
||||||
|
while (1) {
|
||||||
|
- int rc = readdir_r(dir, &entry, &result);
|
||||||
|
- if (rc != 0)
|
||||||
|
- break;
|
||||||
|
- if (result == NULL)
|
||||||
|
+ struct dirent *entry = readdir(dir);
|
||||||
|
+ if (entry == NULL)
|
||||||
|
break;
|
||||||
|
|
||||||
|
- if (!strcmp(entry.d_name, "..") || !strcmp(entry.d_name, "."))
|
||||||
|
+ if (!strcmp(entry->d_name, "..") || !strcmp(entry->d_name, "."))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
- ssize_t size = get_file_data_size(dfd, entry.d_name);
|
||||||
|
+ ssize_t size = get_file_data_size(dfd, entry->d_name);
|
||||||
|
if (size < 0) {
|
||||||
|
continue;
|
||||||
|
} else if (size == 2084) {
|
||||||
|
--
|
||||||
|
2.7.4
|
||||||
|
|
||||||
@@ -0,0 +1,13 @@
|
|||||||
|
FILESEXTRAPATHS_prepend := "${THISDIR}/efivar:"
|
||||||
|
|
||||||
|
SRC_URI += "\
|
||||||
|
file://Remove-use-of-deprecated-readdir_r.patch \
|
||||||
|
"
|
||||||
|
|
||||||
|
# In dp.h, 'for' loop initial declarations are used
|
||||||
|
CFLAGS_append = " -std=gnu99"
|
||||||
|
|
||||||
|
# In order to install headers and libraries to sysroot
|
||||||
|
do_install_append() {
|
||||||
|
oe_runmake DESTDIR=${D} install
|
||||||
|
}
|
||||||
179
meta-encrypted-storage/README.md
Normal file
179
meta-encrypted-storage/README.md
Normal file
@@ -0,0 +1,179 @@
|
|||||||
|
### Storage Encryption
|
||||||
|
This feature provides secure storage for application data. Some applications
|
||||||
|
need secure storage for sensitive data which must not be accessible to another
|
||||||
|
device. For example, only an application with the right signature can update
|
||||||
|
the data on an encrypted SD card. If you move that SD card to another device,
|
||||||
|
the data cannot be either read or updated. One application of this capability
|
||||||
|
is a POS application. The application keeps tax information in secure storage
|
||||||
|
that cannot be modified by another device.
|
||||||
|
|
||||||
|
This feature gives 2 types of granularity for storage encryption. Data volume
|
||||||
|
encryption allows the user to create encryption partition with a passphrase
|
||||||
|
typed by the end user. Root filesystem encryption enables the data encryption
|
||||||
|
on the entire rootfs except the boot partition.
|
||||||
|
|
||||||
|
Both types of storage encryption are based on device-mapper crypt target,
|
||||||
|
which provides transparent encryption of block devices using the kernel crypto
|
||||||
|
API. Additionally, the utility cryptsetup is used to conveniently set up disk
|
||||||
|
encryption, aka LUKS partition, based on device-mapper crypt target.
|
||||||
|
|
||||||
|
Due to the use of TPM state to seal the passphrase used to encrypt the storage,
|
||||||
|
the encrypted storage cannot be accessed on another machine, preventing from
|
||||||
|
the so-called offline attack.
|
||||||
|
|
||||||
|
### Dependency
|
||||||
|
This feature depends on meta-tpm2.
|
||||||
|
|
||||||
|
Note:
|
||||||
|
Even though the hardware doesn't have a TPM 2.0 device, this feature can still
|
||||||
|
run on it, although without the guarantee of compromise detection.
|
||||||
|
|
||||||
|
### Limit
|
||||||
|
- TPM 2.0 is validated and officially supported. But TPM 1.2 device is not
|
||||||
|
supported by this feature.
|
||||||
|
|
||||||
|
### Data Volume Encryption
|
||||||
|
#### Use case 1: manual operation
|
||||||
|
##### Create the LUKS partition
|
||||||
|
```
|
||||||
|
# cryptsetup --type luks --cipher aes-xts-plain --hash sha256 \
|
||||||
|
--use-random luksFormat /dev/$dev
|
||||||
|
```
|
||||||
|
where $dev is the device node of the partition to be encrypted.
|
||||||
|
|
||||||
|
This command initializes a LUKS partition and prompts to input an initial
|
||||||
|
passphrase used to encrypt the data. Don't disclose the passphrase used for
|
||||||
|
product.
|
||||||
|
|
||||||
|
##### Open the LUKS partition
|
||||||
|
```
|
||||||
|
# cryptsetup luksOpen /dev/$dev $name
|
||||||
|
```
|
||||||
|
This command opens the LUKS device $dev and sets up a mapping $name after
|
||||||
|
successful verification of the supplied passphrase typed interactively. From
|
||||||
|
now on, the data written to /dev/mapper/$name is encrypted and the data
|
||||||
|
read back from /dev/mapper/$name is decrypted transparently and automatically.
|
||||||
|
|
||||||
|
##### Create the filesystem on top of the LUKS partition
|
||||||
|
The user can run any available filesytem formatting program on
|
||||||
|
/dev/mapper/$name to create the filesytem with the data encryption.
|
||||||
|
|
||||||
|
##### Close the LUKS partition
|
||||||
|
```
|
||||||
|
# cryptsetup luksClose $name
|
||||||
|
```
|
||||||
|
This command removes the existing mapping $name and wipes the key from kernel
|
||||||
|
memory.
|
||||||
|
|
||||||
|
To access the encryped partition, follow the instruction "Open the LUKS partition"
|
||||||
|
and then manually mount /dev/mapper/$name to a mount point.
|
||||||
|
|
||||||
|
#### Use case 2: luks-setup.sh
|
||||||
|
This script provides a semi automatic method to set up LUKS partition. The user
|
||||||
|
still needs to manually create the filesystem on top of the newly created LUKS
|
||||||
|
partition.
|
||||||
|
|
||||||
|
##### LUKS partition creation
|
||||||
|
In runtime, for example, create LUKS partition on /dev/sdb1 with the
|
||||||
|
name "my_luks_part":
|
||||||
|
```
|
||||||
|
# luks-setup.sh -d /dev/sdb1 -n my_luks_name -e
|
||||||
|
```
|
||||||
|
Note: if TPM is detected, the passphrase will be generated automatically.
|
||||||
|
|
||||||
|
For more uses about luks-setup.sh, run it with -h option.
|
||||||
|
|
||||||
|
##### Retrieve the passphrase
|
||||||
|
```
|
||||||
|
# cryptfs-tpm2 -q unseal passphrase -P sha1 -o /tmp/passphrase
|
||||||
|
```
|
||||||
|
This command will unseal the passphrase from TPM device and save the content
|
||||||
|
of passphrase to the file /tmp/passphrase.
|
||||||
|
|
||||||
|
The passphrase should not be disclosed and needs to be backed up to a off-line
|
||||||
|
storage.
|
||||||
|
|
||||||
|
##### Open the LUKS partition
|
||||||
|
```
|
||||||
|
# cryptsetup luksOpen --key-file /tmp/passphrase /dev/$dev $name
|
||||||
|
```
|
||||||
|
##### Mount the LUKS partition
|
||||||
|
```
|
||||||
|
# mount /dev/mapper/$name $mount_point
|
||||||
|
```
|
||||||
|
The remaining operations are left to the user. Don't forget to close the LUKS
|
||||||
|
partition if not used.
|
||||||
|
|
||||||
|
Note:
|
||||||
|
If TPM device exists in the system, the passphrase will be bound to PCR 7,
|
||||||
|
gating the unseal operation. If the value of PCR 7 when unsealing the
|
||||||
|
passphrase doesn't match up the value when creating the passphrase, the
|
||||||
|
passphrase cannot be unsealed. The value of PCR 7 is usually affected by the
|
||||||
|
status of UEFI secure boot.
|
||||||
|
|
||||||
|
### Root Filesystem Encryption
|
||||||
|
This enables the data encryption on the rootfs without the need of a human
|
||||||
|
entering an user passphrase. Therefore, it is required to employ an initramfs
|
||||||
|
where the unique identity from the platform is collected from the devices on
|
||||||
|
the platform and used to unlock the root filesystem encryption. Meanwhile, use
|
||||||
|
TPM to protect the user passphrase for volume decryption to avoid disclosing
|
||||||
|
the user passphrase. If the TPM device is not detected, the end user will be
|
||||||
|
prompted to type the user passphrase.
|
||||||
|
|
||||||
|
#### Operations
|
||||||
|
Note:
|
||||||
|
The instructions below with the prefix "[TPM]" indicate the operation
|
||||||
|
requires TPM device. Oppositely, the prefix "[Non-TPM]" indicates this
|
||||||
|
operation is required if the target board doesn't have a TPM device.
|
||||||
|
|
||||||
|
- Ensure a hard drive is attached on target board
|
||||||
|
WARNNING: the following instructions will wipe all data in the hard drive.
|
||||||
|
|
||||||
|
- Create overc installer on a USB device
|
||||||
|
Refer to layers/meta-overc/README.install for the details about how to
|
||||||
|
run cubeit to install overc installer to a USB device.
|
||||||
|
|
||||||
|
- Attach the USB device to the board
|
||||||
|
|
||||||
|
- Power on
|
||||||
|
|
||||||
|
- [TPM] Clear TPM
|
||||||
|
Refer to meta-tpm2/README.md for the details.
|
||||||
|
|
||||||
|
- Boot to Linux
|
||||||
|
|
||||||
|
- Install overc runtime on the hard drive
|
||||||
|
Refer to layers/meta-overc/README.install for the details about how to
|
||||||
|
run cubeit-installer to install overc runtime to a hard drive. In
|
||||||
|
addition, beware of specifying "--encrypt" option to set up an
|
||||||
|
encrypted rootfs.
|
||||||
|
|
||||||
|
- Reboot
|
||||||
|
After reboot to initramfs, it employs a init script to transparently
|
||||||
|
unseal the passphrase and mount the rootfs without any interaction.
|
||||||
|
|
||||||
|
### Best Practice
|
||||||
|
- The benefit of anchoring the TPM is that the machine status cannot be
|
||||||
|
compromised by any attack. If compromised, the system cannot boot up
|
||||||
|
due to the failure when mouting the rootfs, or access the encrypted partition
|
||||||
|
when mounting the LUKS partition. This is caused by the fact that the content
|
||||||
|
of PCR 7 is different with the value when creating the encrypted storage.
|
||||||
|
Usually, the content of PCR 7 is calculated based on the status of UEFI
|
||||||
|
secure boot.
|
||||||
|
|
||||||
|
Based on the above conclusion, it is recommended to provision UEFI secure
|
||||||
|
boot and turn on it prior to setting up the encrypted storage.
|
||||||
|
|
||||||
|
- The non-default seal secret is supported to provide extra protection, and it
|
||||||
|
is user configurable. Modify the values of CRYPTFS_TPM2_PRIMARY_KEY_SECRET
|
||||||
|
and CRYPTFS_TPM2_PASSPHRASE_SECRET in cryptfs-tpm2 with your preference.
|
||||||
|
|
||||||
|
### Known Issues
|
||||||
|
- The default IMA rules provides the ability of measuring the boot components
|
||||||
|
and calculating the aggregate integrity value for attesting. However, this
|
||||||
|
function conflicts with this feature which employs PCR policy session to
|
||||||
|
retrieve the passphrase in a safe way. If the installer enables both of
|
||||||
|
them, the default IMA rules will be not used.
|
||||||
|
|
||||||
|
### Reference
|
||||||
|
- [OpenEmbedded layer for TPM 2.0 enablement](https://github.com/jiazhang0/meta-tpm2)
|
||||||
15
meta-encrypted-storage/conf/layer.conf
Normal file
15
meta-encrypted-storage/conf/layer.conf
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
# We have a conf and classes directory, add to BBPATH
|
||||||
|
BBPATH .= ":${LAYERDIR}"
|
||||||
|
|
||||||
|
# We have recipes-* directories, add to BBFILES
|
||||||
|
BBFILES += "${LAYERDIR}/recipes-*/*/*.bb \
|
||||||
|
${LAYERDIR}/recipes-*/*/*.bbappend"
|
||||||
|
|
||||||
|
BBFILE_COLLECTIONS += "encrypted-storage"
|
||||||
|
BBFILE_PATTERN_encrypted-storage = "^${LAYERDIR}/"
|
||||||
|
BBFILE_PRIORITY_encrypted-storage = "10"
|
||||||
|
|
||||||
|
LAYERDEPENDS_encrypted-storage = "\
|
||||||
|
core \
|
||||||
|
tpm2 \
|
||||||
|
"
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
include packagegroup-encrypted-storage.inc
|
||||||
|
|
||||||
|
DESCRIPTION = "The packages used for encrypted storage in initramfs."
|
||||||
|
|
||||||
|
RDEPENDS_${PN} += " \
|
||||||
|
cryptfs-tpm2-initramfs \
|
||||||
|
packagegroup-tpm2-initramfs \
|
||||||
|
"
|
||||||
@@ -0,0 +1,14 @@
|
|||||||
|
include packagegroup-encrypted-storage.inc
|
||||||
|
|
||||||
|
DESCRIPTION = "The packages used for encrypted storage."
|
||||||
|
|
||||||
|
# Install the minimal stuffs only for the linux rootfs.
|
||||||
|
# The common packages shared between initramfs and rootfs
|
||||||
|
# are listed in the .inc.
|
||||||
|
# @util-linux: fdisk
|
||||||
|
# @parted: parted
|
||||||
|
RDEPENDS_${PN} += " \
|
||||||
|
util-linux-fdisk \
|
||||||
|
parted \
|
||||||
|
packagegroup-tpm2 \
|
||||||
|
"
|
||||||
@@ -0,0 +1,25 @@
|
|||||||
|
LICENSE = "MIT"
|
||||||
|
LIC_FILES_CHKSUM = "file://${COREBASE}/LICENSE;md5=4d92cd373abda3937c2bc47fbc49d690 \
|
||||||
|
file://${COREBASE}/meta/COPYING.MIT;md5=3da9cfbcb788c80a0384361b4de20420"
|
||||||
|
|
||||||
|
ALLOW_EMPTY_${PN} = "1"
|
||||||
|
|
||||||
|
S = "${WORKDIR}"
|
||||||
|
|
||||||
|
# Install the minimal stuffs for the common uses between initramfs
|
||||||
|
# and linux rootfs.
|
||||||
|
# @util-linux: mount, umount
|
||||||
|
# @cryptsetup: cryptsetup
|
||||||
|
# @cryptfs-tpm: tpm_gen_dmcrypt_key, tpm_unwrap_dmcrypt_key
|
||||||
|
# @kmod: modprobe
|
||||||
|
# @coreutils: cat, mkdir, mknod, cp, rm
|
||||||
|
# @trousers: tcsd
|
||||||
|
RDEPENDS_${PN} = " \
|
||||||
|
util-linux-mount \
|
||||||
|
util-linux-umount \
|
||||||
|
cryptsetup \
|
||||||
|
kmod \
|
||||||
|
coreutils \
|
||||||
|
cryptfs-tpm2 \
|
||||||
|
procps \
|
||||||
|
"
|
||||||
@@ -0,0 +1,6 @@
|
|||||||
|
FILESEXTRAPATHS_prepend := "${THISDIR}/linux-yocto:"
|
||||||
|
|
||||||
|
SRC_URI += " \
|
||||||
|
${@bb.utils.contains('DISTRO_FEATURES', 'encrypted-storage', \
|
||||||
|
'file://dmcrypt.scc file://dmcrypt.cfg', '', d)} \
|
||||||
|
"
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
include linux-yocto-encrypted-storage.inc
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
# Enable device-mapper crypt target
|
||||||
|
CONFIG_DM_CRYPT=y
|
||||||
|
|
||||||
|
# Enable the default cipher-spec for LUKS
|
||||||
|
CONFIG_CRYPTO_AES=y
|
||||||
|
CONFIG_CRYPTO_AES_NI_INTEL=y
|
||||||
|
CONFIG_CRYPTO_XTS=y
|
||||||
|
|
||||||
|
# Use entropy-strong source for RNG
|
||||||
|
CONFIG_HW_RANDOM=y
|
||||||
|
CONFIG_HW_RANDOM_TPM=m
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
kconf non-hardware dmcrypt.cfg
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
include linux-yocto-encrypted-storage.inc
|
||||||
@@ -0,0 +1,55 @@
|
|||||||
|
SUMMARY = "A tool used to create, persist, evict a passphrase \
|
||||||
|
for full-disk-encryption with TPM 2.0"
|
||||||
|
DESCRIPTION = " \
|
||||||
|
This project provides with an implementation for \
|
||||||
|
creating, persisting and evicting a passphrase with TPM 2.0. \
|
||||||
|
The passphrase and its associated primary key are automatically \
|
||||||
|
created by RNG engine in TPM. In order to avoid saving the \
|
||||||
|
context file, the created passphrase and primary key are always \
|
||||||
|
persistent in TPM. \
|
||||||
|
"
|
||||||
|
SECTION = "devel"
|
||||||
|
LICENSE = "BSD-3-Clause"
|
||||||
|
LIC_FILES_CHKSUM = "file://${S}/LICENSE;md5=89c8ce1346a3dfe75379e84f3ba9d641"
|
||||||
|
|
||||||
|
SRC_URI = " \
|
||||||
|
git://github.com/WindRiver-OpenSourceLabs/cryptfs-tpm2.git \
|
||||||
|
"
|
||||||
|
SRCREV = "32b49092d54b3d59c482d77d5eb1e36993912e89"
|
||||||
|
PV = "0.6.0+git${SRCPV}"
|
||||||
|
|
||||||
|
DEPENDS += "tpm2.0-tss tpm2-abrmd pkgconfig-native"
|
||||||
|
RDEPENDS_${PN} += "libtss2 libtctidevice libtctisocket"
|
||||||
|
|
||||||
|
PACKAGES =+ " \
|
||||||
|
${PN}-initramfs \
|
||||||
|
"
|
||||||
|
|
||||||
|
PARALLEL_MAKE = ""
|
||||||
|
|
||||||
|
S = "${WORKDIR}/git"
|
||||||
|
|
||||||
|
EXTRA_OEMAKE = " \
|
||||||
|
sbindir="${sbindir}" \
|
||||||
|
libdir="${libdir}" \
|
||||||
|
includedir="${includedir}" \
|
||||||
|
tpm2_tss_includedir="${STAGING_INCDIR}/sapi" \
|
||||||
|
tpm2_tss_libdir="${STAGING_LIBDIR}" \
|
||||||
|
tpm2_tabrmd_includedir="${STAGING_INCDIR}" \
|
||||||
|
CC="${CC}" \
|
||||||
|
PKG_CONFIG="${STAGING_BINDIR_NATIVE}/pkg-config" \
|
||||||
|
EXTRA_CFLAGS="${CFLAGS}" \
|
||||||
|
EXTRA_LDFLAGS="${LDFLAGS}" \
|
||||||
|
"
|
||||||
|
|
||||||
|
do_install() {
|
||||||
|
oe_runmake install DESTDIR="${D}"
|
||||||
|
|
||||||
|
if [ x"${@bb.utils.contains('DISTRO_FEATURES', 'encrypted-storage', '1', '0', d)}" = x"1" ]; then
|
||||||
|
install -m 0500 ${S}/script/init.cryptfs ${D}
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
FILES_${PN}-initramfs = "\
|
||||||
|
/init.cryptfs \
|
||||||
|
"
|
||||||
17
meta-integrity/COPYING.MIT
Normal file
17
meta-integrity/COPYING.MIT
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
in the Software without restriction, including without limitation the rights
|
||||||
|
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
copies of the Software, and to permit persons to whom the Software is
|
||||||
|
furnished to do so, subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in
|
||||||
|
all copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
|
THE SOFTWARE.
|
||||||
166
meta-integrity/README.md
Normal file
166
meta-integrity/README.md
Normal file
@@ -0,0 +1,166 @@
|
|||||||
|
### meta-integrity
|
||||||
|
OpenEmbedded layer for Linux integrity support
|
||||||
|
|
||||||
|
#### Integrity Measurement Architecture (IMA)
|
||||||
|
The Linux IMA subsystem introduces hooks within the Linux kernel to support
|
||||||
|
measuring the integrity of files that are loaded (including application code)
|
||||||
|
before it is executed or mmap()ed to memory. The measured value (hash) is then
|
||||||
|
registered in a log that can be consulted by administrators.
|
||||||
|
|
||||||
|
To support proven integrity of the files, the IMA subsystem can interact with
|
||||||
|
the TPM chip within the system to protect the registered hashes from tampering
|
||||||
|
by a rogue administrator or application. The IMA subsystem, as already
|
||||||
|
supported by the Linux kernel, supports reporting on the hashes of files and
|
||||||
|
commands ran by privileged accounts (and more if you create your own
|
||||||
|
measurement policies).
|
||||||
|
|
||||||
|
In addition, IMA appraisal can even register the measured value as an extended
|
||||||
|
attribute, and after subsequent measurement(s) validate this extended attribute
|
||||||
|
against the measured value and refuse to load the file (or execute the
|
||||||
|
application) if the hash does not match. In that case, the IMA subsystem allows
|
||||||
|
files and applications to be loaded if the hashes match (and will save the
|
||||||
|
updated hash if the file is modified) but refuse to load it if it doesn't. This
|
||||||
|
provides some protection against offline tampering of the files.
|
||||||
|
|
||||||
|
NOTE: Extended file system attribute is required for IMA appraisal, but not
|
||||||
|
all file systems can support it. Typically, the pseudo file systems, such as
|
||||||
|
sysfs, proc, tmpfs and ramfs, certain disk-based file systems, such as FAT,
|
||||||
|
and network file systems, such as NFS, don't support extended attribute,
|
||||||
|
meaning IMA appraisal is not available with them.
|
||||||
|
|
||||||
|
##### Dependency
|
||||||
|
- meta-tpm
|
||||||
|
This layer provides the kernel configurations for TPM 1.x enablement.
|
||||||
|
|
||||||
|
- meta-tpm2
|
||||||
|
This layer provides the kernel configurations for TPM 2.0 enablement.
|
||||||
|
|
||||||
|
##### Use The External IMA Policy
|
||||||
|
initramfs is a good place to run some IMA initializations, such as loading
|
||||||
|
the IMA policy, as well as the public keys used to verify IMA signatures.
|
||||||
|
|
||||||
|
###### The default external IMA policy
|
||||||
|
The default external IMA policy enforces appraising all the executable, shared
|
||||||
|
library, kernel modules and firmwares with the digital signature in the
|
||||||
|
effective root identity (euid=0). Hence, the opportunity of loading the default
|
||||||
|
external IMA policy occurs at the end of initramfs initializations, just before
|
||||||
|
switch_root.
|
||||||
|
|
||||||
|
Instead of running switch_root directly from initramfs, a statically linked
|
||||||
|
switch_root from the real rootfs is called and it must be already signed
|
||||||
|
properly. Otherwise, switch_root will fail to mount the real rootfs and kernel
|
||||||
|
panic will happen due to this failure.
|
||||||
|
|
||||||
|
The default external IMA policy is located at `/etc/ima_policy.default` in
|
||||||
|
initramfs. If a custom external IMA policy file exists, the default external
|
||||||
|
IMA policy file won't be used any more.
|
||||||
|
|
||||||
|
The default external IMA policy enables the following constraint conditions:
|
||||||
|
- Appraise the files for exec'd (the executables), files mmap'd for exec
|
||||||
|
(shared libraries), kernel modules and firmwares in effective root identity
|
||||||
|
(euid=0).
|
||||||
|
- Enforce verifying the IMA signature when running the executables, shared
|
||||||
|
libraries, kernel modules and firmwares.
|
||||||
|
- Deny to run the newly created executables, shared libraries, kernel modules
|
||||||
|
and firmwares.
|
||||||
|
- Deny to run the tampered executables, shared libraries, kernel modules and
|
||||||
|
firmwares.
|
||||||
|
- Deny to run any executables, shared libraries, kernel modules and firmwares
|
||||||
|
in the filesystems without file extended attribute supported.
|
||||||
|
- Allow to run the manually signed executables, shared libraries, kernel
|
||||||
|
modules and firmwares.
|
||||||
|
- Allow to run the updated executables, shared libraries, kernel modules and
|
||||||
|
firmwares during RPM installation.
|
||||||
|
- Note the different behaviors when executing a script.
|
||||||
|
e.g, launching a python script with "./test.py" is allowed only when test.py
|
||||||
|
is signed, and launching a python script with "python test.py" is always
|
||||||
|
allowed as long as the python interpreter is signed.
|
||||||
|
|
||||||
|
###### The custom external IMA policy
|
||||||
|
If the default external IMA policy cannot meet the protection requirement, it
|
||||||
|
is allowed to define the custom external IMA policy.
|
||||||
|
|
||||||
|
- Deploy the custom policy file to installer image
|
||||||
|
|
||||||
|
- Create `/opt/installer/sbin/config-installer.sh` in installer image
|
||||||
|
Define the IMA_POLICY variable, pointing to the path of policy file.
|
||||||
|
|
||||||
|
The custom external IMA policy file is eventually installed to `/etc/ima_policy`
|
||||||
|
in initramfs.
|
||||||
|
|
||||||
|
##### IMA certificate & private Key
|
||||||
|
The private key come in two flavors; one used by an installer to sign all
|
||||||
|
regular files in rootfs and one used by RPM to re-sign the executable, shared
|
||||||
|
library, kernel module and firmware during RPM installation. Correspondingly,
|
||||||
|
the IMA certificate is used to verify the IMA signature signed by the private
|
||||||
|
key.
|
||||||
|
|
||||||
|
In addition, initramfs is a good place to import the IMA certificate likewise.
|
||||||
|
|
||||||
|
###### The default IMA certificate & private key
|
||||||
|
The default IMA certificate & private key are generated by the build system. By
|
||||||
|
default, the sample keys are used for the purpose of development and
|
||||||
|
demonstration. Please ensure you know what your risk is to use the sample keys
|
||||||
|
in your product, because they are completely public.
|
||||||
|
|
||||||
|
### Best practice
|
||||||
|
The following best practices should be applied with using IMA.
|
||||||
|
|
||||||
|
- Enable UEFI/MOK secure boot
|
||||||
|
UEFI/MOK secure boot can verify the integrity of initramfs, providing the
|
||||||
|
protection against tampering of the external IMA policy files and IMA public
|
||||||
|
keys stored in initramfs.
|
||||||
|
|
||||||
|
- Moderate measuring
|
||||||
|
Measuring the files owned by non-root user may introduce malicious attack.
|
||||||
|
Malicious user may create lots of files with different names or trigger
|
||||||
|
violation conditions to generate a mass of event logs recorded in the runtime
|
||||||
|
measurement list, and thus exhaust the persistent kernel memory.
|
||||||
|
|
||||||
|
- Performance influence
|
||||||
|
Moderate policy can make a good balance between the performance and security.
|
||||||
|
Tune the default external policy (`/etc/ima_policy.default`) and modulate the
|
||||||
|
custom policy for the product requirement.
|
||||||
|
|
||||||
|
- Use IMA digital signature to protect the executable
|
||||||
|
Using the digital signature scheme DIGSIG is safer than digest-based scheme.
|
||||||
|
Meanwhile, use `appraise_type=imasig` in your IMA policy to enforce running
|
||||||
|
this.
|
||||||
|
|
||||||
|
- Use the measurement and audit rules together
|
||||||
|
The runtime measurement list is unable to track down the order of changes for
|
||||||
|
a file, e.g, a file content varies in order of X -> Y -> X. However, audit log
|
||||||
|
can record these changes in the right order.
|
||||||
|
|
||||||
|
##### Known Issues
|
||||||
|
- The following operations may break the behavior of appraisal and cause the
|
||||||
|
failure of launching the executables, shared libraries, kernel modules and
|
||||||
|
firmwares:
|
||||||
|
- the syscalls used to set file last access and modification times.
|
||||||
|
- the syscalls used to set ownership of a file.
|
||||||
|
- the syscalls used to set permissions of a file.
|
||||||
|
|
||||||
|
To fix the failure, manually re-sign the affected file.
|
||||||
|
|
||||||
|
Note: RPM installation violates the IMA appraisal but its post_install
|
||||||
|
operation will always re-sign the affected files.
|
||||||
|
|
||||||
|
- Overwriting an existing file with the same content is deemed as tampering of
|
||||||
|
the file.
|
||||||
|
|
||||||
|
- The default IMA rules provides the ability of measuring the boot components
|
||||||
|
and calculating the aggregate integrity value for attesting. However, this
|
||||||
|
function conflicts with encrypted-storage feature which employs PCR policy
|
||||||
|
session to retrieve the passphrase in a safe way. If the installer enables
|
||||||
|
both of them, the default IMA rules will be not used.
|
||||||
|
|
||||||
|
### Reference
|
||||||
|
[IMA wiki page](https://sourceforge.net/p/linux-ima/wiki/Home/)
|
||||||
|
|
||||||
|
[OpenEmbedded layer for EFI Secure Boot](https://github.com/jiazhang0/meta-efi-secure-boot)
|
||||||
|
|
||||||
|
[OpenEmbedded layer for signing key management](https://github.com/jiazhang0/meta-signing-key)
|
||||||
|
|
||||||
|
[OpenEmbedded layer for TPM 1.x](https://github.com/jiazhang0/meta-tpm)
|
||||||
|
|
||||||
|
[OpenEmbedded layer for TPM 2.0](https://github.com/jiazhang0/meta-tpm2)
|
||||||
156
meta-integrity/classes/rpm5-ima.bbclass
Normal file
156
meta-integrity/classes/rpm5-ima.bbclass
Normal file
@@ -0,0 +1,156 @@
|
|||||||
|
inherit package
|
||||||
|
|
||||||
|
PACKAGEFUNCS =+ "package_ima_hook"
|
||||||
|
|
||||||
|
# security.ima is generated during the RPM build, and the base64-encoded
|
||||||
|
# value is written during RPM installation. In addition, if the private
|
||||||
|
# key is deployed on board, re-sign the updated files during RPM
|
||||||
|
# installation in higher priority.
|
||||||
|
python package_ima_hook() {
|
||||||
|
packages = d.getVar('PACKAGES', True)
|
||||||
|
pkgdest = d.getVar('PKGDEST', True)
|
||||||
|
ima_signing_blacklist = d.getVar('IMA_SIGNING_BLACKLIST', True)
|
||||||
|
ima_keys_dir = d.getVar('IMA_KEYS_DIR', True)
|
||||||
|
|
||||||
|
pkg_suffix_blacklist = ('dbg', 'dev', 'doc', 'locale', 'staticdev')
|
||||||
|
|
||||||
|
pkg_blacklist = ()
|
||||||
|
with open(ima_signing_blacklist, 'r') as f:
|
||||||
|
pkg_blacklist = [ _.strip() for _ in f.readlines() ]
|
||||||
|
pkg_blacklist = tuple(pkg_blacklist)
|
||||||
|
|
||||||
|
import base64, pipes, stat
|
||||||
|
|
||||||
|
for pkg in packages.split():
|
||||||
|
if (pkg.split('-')[-1] in pkg_suffix_blacklist) is True:
|
||||||
|
continue
|
||||||
|
|
||||||
|
if pkg.startswith(pkg_blacklist) is True:
|
||||||
|
continue
|
||||||
|
|
||||||
|
bb.note("Writing IMA %%post hook for %s ..." % pkg)
|
||||||
|
|
||||||
|
pkgdestpkg = os.path.join(pkgdest, pkg)
|
||||||
|
|
||||||
|
cmd = 'evmctl ima_sign --hashalgo sha256 -n --sigfile --key %s/x509_ima.key ' % (ima_keys_dir)
|
||||||
|
sig_list = []
|
||||||
|
pkg_sig_list = []
|
||||||
|
|
||||||
|
for _ in pkgfiles[pkg]:
|
||||||
|
# Ignore the symbol links.
|
||||||
|
if os.path.islink(_):
|
||||||
|
continue
|
||||||
|
|
||||||
|
# IMA appraisal is only applied to the regular file.
|
||||||
|
if not stat.S_ISREG(os.stat(_)[stat.ST_MODE]):
|
||||||
|
continue
|
||||||
|
|
||||||
|
bb.note("Preparing to sign %s ..." % _)
|
||||||
|
|
||||||
|
sh_name = pipes.quote(_)
|
||||||
|
print("Signing command: %s" % cmd + sh_name)
|
||||||
|
rc, res = oe.utils.getstatusoutput(cmd + sh_name + " >/dev/null")
|
||||||
|
if rc:
|
||||||
|
bb.fatal('Calculate IMA signature for %s failed with exit code %s:\n%s' % \
|
||||||
|
(_, rc, res if res else ""))
|
||||||
|
|
||||||
|
with open(_ + '.sig', 'rb') as f:
|
||||||
|
s = str(base64.b64encode(f.read()).decode('ascii')) + '|'
|
||||||
|
sig_list.append(s + os.sep + os.path.relpath(_, pkgdestpkg))
|
||||||
|
|
||||||
|
os.remove(_ + '.sig')
|
||||||
|
|
||||||
|
ima_sig_list = '&'.join(sig_list)
|
||||||
|
|
||||||
|
# When the statically linked binary is updated, use the
|
||||||
|
# dynamically linked one to resign or set. This situation
|
||||||
|
# occurs in runtime only.
|
||||||
|
setfattr_bin = 'setfattr.static'
|
||||||
|
evmctl_bin = 'evmctl.static'
|
||||||
|
# We don't want to create a statically linked echo program
|
||||||
|
# any more.
|
||||||
|
safe_echo = '1'
|
||||||
|
if pkg == 'attr-setfattr.static':
|
||||||
|
setfattr_bin = 'setfattr'
|
||||||
|
elif pkg == 'ima-evm-utils-evmctl.static':
|
||||||
|
evmctl_bin = 'evmctil'
|
||||||
|
elif pkg == 'coreutils':
|
||||||
|
safe_echo = '0'
|
||||||
|
|
||||||
|
# The %post is dynamically constructed according to the currently
|
||||||
|
# installed package and enviroment.
|
||||||
|
postinst = r'''#!/bin/sh
|
||||||
|
|
||||||
|
# %post hook for IMA appraisal
|
||||||
|
ima_resign=0
|
||||||
|
sig_list="''' + ima_sig_list + r'''"
|
||||||
|
|
||||||
|
if [ -z "$D" ]; then
|
||||||
|
evmctl_bin="${sbindir}/''' + evmctl_bin + r'''"
|
||||||
|
setfattr_bin="${bindir}/''' + setfattr_bin + r'''"
|
||||||
|
|
||||||
|
[ -f "/etc/keys/privkey_evm.pem" -a -x "$evmctl_bin" ] && \
|
||||||
|
ima_resign=1
|
||||||
|
|
||||||
|
safe_echo="''' + safe_echo + r'''"
|
||||||
|
|
||||||
|
cond_print()
|
||||||
|
{
|
||||||
|
[ $safe_echo = "1" ] && echo $1
|
||||||
|
}
|
||||||
|
|
||||||
|
saved_IFS="$IFS"
|
||||||
|
IFS="&"
|
||||||
|
for entry in $sig_list; do
|
||||||
|
IFS="|"
|
||||||
|
|
||||||
|
tokens=""
|
||||||
|
for token in $entry; do
|
||||||
|
tokens="$tokens$token|"
|
||||||
|
done
|
||||||
|
|
||||||
|
for sig in $tokens; do
|
||||||
|
break
|
||||||
|
done
|
||||||
|
|
||||||
|
IFS="$saved_IFS"
|
||||||
|
|
||||||
|
f="$token"
|
||||||
|
|
||||||
|
# If the filesystem doesn't support xattr, skip the following steps.
|
||||||
|
res=`"$setfattr_bin" -x security.ima "$f" 2>&1 | grep "Operation not supported$"`
|
||||||
|
[ x"$res" != x"" ] && {
|
||||||
|
cond_print "Current file system doesn't support to set xattr"
|
||||||
|
break
|
||||||
|
}
|
||||||
|
|
||||||
|
if [ $ima_resign -eq 0 ]; then
|
||||||
|
cond_print "Setting up security.ima for $f ..."
|
||||||
|
|
||||||
|
"$setfattr_bin" -n security.ima -v "0s$sig" "$f" || {
|
||||||
|
err=$?
|
||||||
|
cond_print "Unable to set up security.ima for $f (err: $err)"
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
else
|
||||||
|
cond_print "IMA signing for $f ..."
|
||||||
|
|
||||||
|
"$evmctl_bin" ima_sign --hashalgo sha256 "$f" || {
|
||||||
|
err=$?
|
||||||
|
cond_print "Unable to sign $f (err: $err)"
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
fi
|
||||||
|
|
||||||
|
IFS="&"
|
||||||
|
done
|
||||||
|
|
||||||
|
IFS="$saved_IFS"
|
||||||
|
fi
|
||||||
|
|
||||||
|
'''
|
||||||
|
postinst = postinst + (d.getVar('pkg_postinst_%s' % pkg, True) or '')
|
||||||
|
d.setVar('pkg_postinst_%s' % pkg, postinst)
|
||||||
|
}
|
||||||
|
|
||||||
|
do_package[depends] += "ima-evm-utils-native:do_populate_sysroot"
|
||||||
19
meta-integrity/conf/layer.conf
Normal file
19
meta-integrity/conf/layer.conf
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
# We have a conf and classes directory, add to BBPATH
|
||||||
|
BBPATH .= ":${LAYERDIR}"
|
||||||
|
|
||||||
|
# We have recipes-* directories, add to BBFILES
|
||||||
|
BBFILES += "${LAYERDIR}/recipes-*/*/*.bb \
|
||||||
|
${LAYERDIR}/recipes-*/*/*.bbappend"
|
||||||
|
|
||||||
|
BBFILE_COLLECTIONS += "integrity"
|
||||||
|
BBFILE_PATTERN_integrity = "^${LAYERDIR}/"
|
||||||
|
BBFILE_PRIORITY_integrity = "10"
|
||||||
|
|
||||||
|
IMA_SIGNING_BLACKLIST ??= "${LAYERDIR}/files/ima_signing_blacklist"
|
||||||
|
|
||||||
|
LAYERDEPENDS_integrity = "\
|
||||||
|
core \
|
||||||
|
signing-key \
|
||||||
|
tpm2 \
|
||||||
|
tpm \
|
||||||
|
"
|
||||||
1
meta-integrity/files/ima_signing_blacklist
Normal file
1
meta-integrity/files/ima_signing_blacklist
Normal file
@@ -0,0 +1 @@
|
|||||||
|
kernel-devsrc
|
||||||
@@ -0,0 +1,12 @@
|
|||||||
|
DESCRIPTION = "Linux Integrity Measurement Architecture (IMA) subsystem for initramfs"
|
||||||
|
|
||||||
|
include packagegroup-ima.inc
|
||||||
|
|
||||||
|
RDEPENDS_${PN} += " \
|
||||||
|
util-linux-mount \
|
||||||
|
util-linux-umount \
|
||||||
|
gawk \
|
||||||
|
ima-policy \
|
||||||
|
key-store-ima-cert \
|
||||||
|
initrdscripts-ima \
|
||||||
|
"
|
||||||
@@ -0,0 +1,21 @@
|
|||||||
|
DESCRIPTION = "Linux Integrity Measurement Architecture (IMA) subsystem"
|
||||||
|
|
||||||
|
include packagegroup-ima.inc
|
||||||
|
|
||||||
|
DEPENDS += " \
|
||||||
|
ima-evm-utils-native \
|
||||||
|
attr-native \
|
||||||
|
"
|
||||||
|
|
||||||
|
RDEPENDS_${PN} += " \
|
||||||
|
attr \
|
||||||
|
util-linux-switch_root.static \
|
||||||
|
attr-setfattr.static \
|
||||||
|
ima-evm-utils-evmctl.static \
|
||||||
|
"
|
||||||
|
|
||||||
|
# Note any private key is not available if user key signing model used.
|
||||||
|
RRECOMMENDS_${PN} += " \
|
||||||
|
key-store-ima-privkey \
|
||||||
|
key-store-system-trusted-privkey \
|
||||||
|
"
|
||||||
@@ -0,0 +1,13 @@
|
|||||||
|
LICENSE = "MIT"
|
||||||
|
LIC_FILES_CHKSUM = "file://${COREBASE}/LICENSE;md5=4d92cd373abda3937c2bc47fbc49d690 \
|
||||||
|
file://${COREBASE}/meta/COPYING.MIT;md5=3da9cfbcb788c80a0384361b4de20420"
|
||||||
|
|
||||||
|
S = "${WORKDIR}"
|
||||||
|
|
||||||
|
ALLOW_EMPTY_${PN} = "1"
|
||||||
|
|
||||||
|
RDEPENDS_${PN} = " \
|
||||||
|
ima-evm-utils \
|
||||||
|
coreutils \
|
||||||
|
grep \
|
||||||
|
"
|
||||||
@@ -0,0 +1,4 @@
|
|||||||
|
# Append iversion option for auto types
|
||||||
|
do_install_append() {
|
||||||
|
sed -i 's/\s*auto\s*defaults/&,iversion/' ${D}${sysconfdir}/fstab
|
||||||
|
}
|
||||||
129
meta-integrity/recipes-core/initrdscripts/files/init.ima
Executable file
129
meta-integrity/recipes-core/initrdscripts/files/init.ima
Executable file
@@ -0,0 +1,129 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
|
||||||
|
# Initramfs script for IMA initialzation
|
||||||
|
#
|
||||||
|
# This script is a halper used to load the external
|
||||||
|
# IMA policy and public keys used to verify the IMA
|
||||||
|
# signature.
|
||||||
|
#
|
||||||
|
# Copyright (c) 2017, Jia Zhang <lans.zhang2008@gmail.com>
|
||||||
|
# All rights reserved.
|
||||||
|
#
|
||||||
|
# See "LICENSE" for license terms.
|
||||||
|
|
||||||
|
# Exit code:
|
||||||
|
# 0 - IMA initialiazation complete
|
||||||
|
# 1 - Kernel doesn't support securityfs
|
||||||
|
# 2 - Kernel doesn't support IMA
|
||||||
|
# 3 - There is no public key to load
|
||||||
|
# 4 - There is no IMA policy file defined
|
||||||
|
# 5 - Unable to load IMA policy file
|
||||||
|
|
||||||
|
# If root directory is not specified, the root of
|
||||||
|
# initramfs assumed.
|
||||||
|
ROOT_DIR="${1}"
|
||||||
|
|
||||||
|
SECURITYFS_DIR="${ROOT_DIR}/sys/kernel/security"
|
||||||
|
|
||||||
|
# The policy files are always placed in initramfs
|
||||||
|
IMA_POLICY=/etc/ima_policy
|
||||||
|
|
||||||
|
SECURITYFS_MOUNTED=0
|
||||||
|
|
||||||
|
function print_critical
|
||||||
|
{
|
||||||
|
printf "\033[1;35m"
|
||||||
|
echo "$@"
|
||||||
|
printf "\033[0m"
|
||||||
|
}
|
||||||
|
|
||||||
|
function print_error
|
||||||
|
{
|
||||||
|
printf "\033[1;31m"
|
||||||
|
echo "$@"
|
||||||
|
printf "\033[0m"
|
||||||
|
}
|
||||||
|
|
||||||
|
function print_warning
|
||||||
|
{
|
||||||
|
printf "\033[1;33m"
|
||||||
|
echo "$@"
|
||||||
|
printf "\033[0m"
|
||||||
|
}
|
||||||
|
|
||||||
|
function print_info
|
||||||
|
{
|
||||||
|
printf "\033[1;32m"
|
||||||
|
echo "$@"
|
||||||
|
printf "\033[0m"
|
||||||
|
}
|
||||||
|
|
||||||
|
function print_verbose
|
||||||
|
{
|
||||||
|
printf "\033[1;36m"
|
||||||
|
echo "$@"
|
||||||
|
printf "\033[0m"
|
||||||
|
}
|
||||||
|
|
||||||
|
function trap_handler
|
||||||
|
{
|
||||||
|
local err=$?
|
||||||
|
|
||||||
|
print_verbose "Cleaning up with exit code $err ..."
|
||||||
|
|
||||||
|
[ $SECURITYFS_MOUNTED -eq 1 ] &&
|
||||||
|
umount "$SECURITYFS_DIR" 2>"${ROOT_DIR}/dev/null"
|
||||||
|
}
|
||||||
|
|
||||||
|
trap "trap_handler $?" SIGINT EXIT
|
||||||
|
|
||||||
|
if grep -q "ima_appraise=off" "${ROOT_DIR}/proc/cmdline"; then
|
||||||
|
print_info "Skip to load the public key and IMA policy"
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
if ! grep -q securityfs "${ROOT_DIR}/proc/mounts"; then
|
||||||
|
! mount -t securityfs none "$SECURITYFS_DIR" 2>"${ROOT_DIR}/dev/null" && {
|
||||||
|
print_error "Unable to mount securityfs filesystem"
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
SECURITYFS_MOUNTED=1
|
||||||
|
securityfs_dir="$SECURITYFS_DIR"
|
||||||
|
else
|
||||||
|
securityfs_dirs="$(grep securityfs ${ROOT_DIR}/proc/mounts | awk '{print $2}')"
|
||||||
|
|
||||||
|
# Use the first one.
|
||||||
|
for securityfs_dir in "$securityfs_dirs"; do
|
||||||
|
break
|
||||||
|
done
|
||||||
|
fi
|
||||||
|
|
||||||
|
[ ! -d "$securityfs_dir/ima" ] &&
|
||||||
|
print_info "IMA is not enabled. Exiting ..." && exit 2
|
||||||
|
|
||||||
|
keyring_id=0x`grep '\skeyring\s*\.ima: ' "${ROOT_DIR}/proc/keys" | awk '{ print $1 }'`
|
||||||
|
|
||||||
|
for key in ${ROOT_DIR}/etc/keys/x509_evm*.pem; do
|
||||||
|
[ ! -s "$key" ] && continue
|
||||||
|
|
||||||
|
if ! evmctl import "$key" "$keyring_id" >"${ROOT_DIR}/dev/null"; then
|
||||||
|
print_critical "Unable to load the public key $key for IMA appraisal"
|
||||||
|
else
|
||||||
|
print_verbose "The external public key $key loaded for IMA appraisal"
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
|
# Attempt to load the default policy.
|
||||||
|
[ ! -f "${IMA_POLICY}" ] && IMA_POLICY="${IMA_POLICY}.default"
|
||||||
|
|
||||||
|
[ ! -f "${IMA_POLICY}" ] && {
|
||||||
|
print_warning "No IMA policy file defined"
|
||||||
|
exit 4
|
||||||
|
}
|
||||||
|
|
||||||
|
cat "${IMA_POLICY}" > "$securityfs_dir/ima/policy" && {
|
||||||
|
exit 0
|
||||||
|
} || {
|
||||||
|
print_critical "Unable to load the IMA policy ${IMA_POLICY}"
|
||||||
|
exit 5
|
||||||
|
}
|
||||||
@@ -0,0 +1,47 @@
|
|||||||
|
DESCRIPTION = "The initrd script for Linux Integrity Measurement Architecture (IMA)"
|
||||||
|
LICENSE = "MIT"
|
||||||
|
LIC_FILES_CHKSUM = "file://${COREBASE}/LICENSE;md5=4d92cd373abda3937c2bc47fbc49d690 \
|
||||||
|
file://${COREBASE}/meta/COPYING.MIT;md5=3da9cfbcb788c80a0384361b4de20420"
|
||||||
|
|
||||||
|
S = "${WORKDIR}"
|
||||||
|
|
||||||
|
ALLOW_EMPTY_${PN} = "1"
|
||||||
|
|
||||||
|
SRC_URI = "\
|
||||||
|
file://init.ima \
|
||||||
|
"
|
||||||
|
|
||||||
|
do_install() {
|
||||||
|
if [ x"${@bb.utils.contains('DISTRO_FEATURES', 'ima', '1', '0', d)}" = x"1" ]; then
|
||||||
|
install -m 0500 ${WORKDIR}/init.ima ${D}
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
FILES_${PN} += " \
|
||||||
|
${@bb.utils.contains('DISTRO_FEATURES', 'ima', '/init.ima', '', d)} \
|
||||||
|
"
|
||||||
|
|
||||||
|
# Install the minimal stuffs only, and don't care how the external
|
||||||
|
# environment is configured.
|
||||||
|
# @bash: sh
|
||||||
|
# @coreutils: echo, mkdir, mknod, dirname, basename, cp, rm, sleep
|
||||||
|
# seq, printf, cut
|
||||||
|
# @grep: grep
|
||||||
|
# @gawk: awk
|
||||||
|
# @kmod: modprobe, depmod
|
||||||
|
# @net-tools: ifconfig
|
||||||
|
# @trousers: tcsd
|
||||||
|
# @procps: pkill
|
||||||
|
# @util-linux: blkid, mount, umount
|
||||||
|
RDEPENDS_${PN} += "\
|
||||||
|
bash \
|
||||||
|
coreutils \
|
||||||
|
grep \
|
||||||
|
gawk \
|
||||||
|
kmod \
|
||||||
|
net-tools \
|
||||||
|
procps \
|
||||||
|
util-linux-blkid \
|
||||||
|
util-linux-mount \
|
||||||
|
util-linux-umount \
|
||||||
|
"
|
||||||
16
meta-integrity/recipes-core/util-linux/util-linux_%.bbappend
Normal file
16
meta-integrity/recipes-core/util-linux/util-linux_%.bbappend
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
PACKAGES =+ "${PN}-switch_root.static"
|
||||||
|
|
||||||
|
CFLAGS_remove += "-pie -fpie"
|
||||||
|
|
||||||
|
do_compile_append_class-target() {
|
||||||
|
${CC} ${CFLAGS} ${LDFLAGS} -static \
|
||||||
|
sys-utils/switch_root.o \
|
||||||
|
-o switch_root.static
|
||||||
|
}
|
||||||
|
|
||||||
|
do_install_append_class-target() {
|
||||||
|
install -d ${D}${sbindir}
|
||||||
|
install -m 0700 ${B}/switch_root.static ${D}${sbindir}/switch_root.static
|
||||||
|
}
|
||||||
|
|
||||||
|
FILES_${PN}-switch_root.static = "${sbindir}/switch_root.static"
|
||||||
@@ -0,0 +1,18 @@
|
|||||||
|
FILESEXTRAPATHS_prepend := "${THISDIR}/linux-yocto:"
|
||||||
|
|
||||||
|
IMA_ENABLED = "${@bb.utils.contains('DISTRO_FEATURES', 'ima', '1', '0', d)}"
|
||||||
|
|
||||||
|
DEPENDS += "${@'key-store openssl-native' if d.getVar('IMA_ENABLED', True) == '1' else ''}"
|
||||||
|
# key-store-ima-cert is required in runtime but we hope it is available
|
||||||
|
# in initramfs only. So we don't add it to RDEPENDS_${PN} here.
|
||||||
|
|
||||||
|
SRC_URI += " \
|
||||||
|
${@'file://ima.scc file://ima.cfg' if d.getVar('IMA_ENABLED', True) == '1' else ''} \
|
||||||
|
"
|
||||||
|
|
||||||
|
do_configure_append() {
|
||||||
|
[ -f "${STAGING_DIR_TARGET}${sysconfdir}/keys/system_trusted_key.pem" ] &&
|
||||||
|
openssl x509 -in "${STAGING_DIR_TARGET}${sysconfdir}/keys/system_trusted_key.pem" \
|
||||||
|
-outform DER -out "${B}/system_trusted_cert.x509" ||
|
||||||
|
true
|
||||||
|
}
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
include linux-yocto-integrity.inc
|
||||||
35
meta-integrity/recipes-kernel/linux/linux-yocto/ima.cfg
Normal file
35
meta-integrity/recipes-kernel/linux/linux-yocto/ima.cfg
Normal file
@@ -0,0 +1,35 @@
|
|||||||
|
..........................................................................
|
||||||
|
. WARNING
|
||||||
|
.
|
||||||
|
. This file is a kernel configuration fragment, and not a full kernel
|
||||||
|
. configuration file. The final kernel configuration is made up of
|
||||||
|
. an assembly of processed fragments, each of which is designed to
|
||||||
|
. capture a specific part of the final configuration (e.g. platform
|
||||||
|
. configuration, feature configuration, and board specific hardware
|
||||||
|
. configuration). For more information on kernel configuration, please
|
||||||
|
. consult the product documentation.
|
||||||
|
.
|
||||||
|
..........................................................................
|
||||||
|
|
||||||
|
CONFIG_IMA=y
|
||||||
|
CONFIG_IMA_MEASURE_PCR_IDX=10
|
||||||
|
# CONFIG_IMA_TEMPLATE is not set
|
||||||
|
# CONFIG_IMA_NG_TEMPLATE=y is not set
|
||||||
|
CONFIG_IMA_SIG_TEMPLATE=y
|
||||||
|
CONFIG_IMA_DEFAULT_TEMPLATE="ima-sig"
|
||||||
|
# CONFIG_IMA_DEFAULT_HASH_SHA1 is not set
|
||||||
|
CONFIG_IMA_DEFAULT_HASH_SHA256=y
|
||||||
|
# CONFIG_IMA_DEFAULT_HASH_SHA512 is not set
|
||||||
|
# CONFIG_IMA_DEFAULT_HASH_WP512 is not set
|
||||||
|
CONFIG_IMA_DEFAULT_HASH="sha256"
|
||||||
|
CONFIG_IMA_APPRAISE=y
|
||||||
|
CONFIG_INTEGRITY_SIGNATURE=y
|
||||||
|
CONFIG_INTEGRITY_ASYMMETRIC_KEYS=y
|
||||||
|
CONFIG_INTEGRITY_TRUSTED_KEYRING=y
|
||||||
|
CONFIG_SYSTEM_TRUSTED_KEYRING=y
|
||||||
|
CONFIG_IMA_LOAD_X509=y
|
||||||
|
CONFIG_IMA_TRUSTED_KEYRING=y
|
||||||
|
CONFIG_IMA_X509_PATH="/etc/keys/x509_evm.der"
|
||||||
|
# CONFIG_IMA_APPRAISE_SIGNED_INIT is not set
|
||||||
|
CONFIG_AUDIT=y
|
||||||
|
CONFIG_INTEGRITY_AUDIT=y
|
||||||
4
meta-integrity/recipes-kernel/linux/linux-yocto/ima.scc
Normal file
4
meta-integrity/recipes-kernel/linux/linux-yocto/ima.scc
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
define KFEATURE_DESCRIPTION "Integrity Measurement Architecture (IMA) enablement"
|
||||||
|
define KFEATURE_COMPATIBILITY board
|
||||||
|
|
||||||
|
kconf non-hardware ima.cfg
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user