mirror of
https://github.com/jiazhang0/meta-secure-core.git
synced 2026-01-11 16:50:12 +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