UEFI Secure Boot
To verify whether UEFI secure boot is enabled, run the following command from the BlueField console:
ubuntu@localhost:~$ sudo mokutil --sb-state
SecureBoot enabled
As UEFI secure boot is not specific to BlueField platforms, please refer to the Canonical documentation online for further information on UEFI secure boot:
Signing binaries is complex as you must create X.509 certificates and enroll them in UEFI or shim which requires a fair amount of prior knowledge of how secure boot works. For that reason, BlueField secured platforms are shipped with all the needed certificates and signed binaries.
To enable UEFI secure boot, you may either import your own X.509 certificates, or more easily, import the NVIDIA X.509 certificate:
Method |
Pros |
Cons |
Enrolling NVIDIA key certificates in the UEFI database |
Easy |
Very limited flexibility; only allows executing NVIDIA binary files |
Dependency on Microsoft or NVIDIA as signing entities |
||
Enrolling your own key certificates in the UEFI database |
Autonomy, as you control your keys (no dependency on Microsoft or NVIDIA as signing entities) |
You must create your own capsule files to enroll and customize UEFI secure boot |
If UEFI secure boot is enabled, then the UEFI databases are populated with NVIDIA self-signed X.509 certificates. The Microsoft certificate is also installed into the UEFI database to ensure that the Ubuntu distribution can boot while UEFI secure boot is enabled.
The pre-installed certificate files are:
NVIDIA PK key certificate
NVIDIA KEK key certificate
NVIDIA db certificate
Microsoft db certificate
If UEFI secure boot is not enabled, then UEFI database certificate files are not installed, and the capsule file /lib/firmware/mellanox/boot/capsule/EnrollKeysCap may be used to populate the UEFI databases and enable UEFI secure boot.
ubuntu@localhost:~$ bfrec --capsule /lib/firmware/mellanox/boot/capsule/EnrollKeysCap
Then reboot in order to process the capsule and enter the update mode.
The capsule file might be used to update the UEFI database. The capsule file is signed with NVIDIA UEFI signing key to allow the capsule processing by UEFI while secure boot is enabled. When UEFI secure boot is enabled, unsigned and/or untrusted, capsule files are rejected for security violation and will not be processed by UEFI.
Note that the capsule file also configures a default password "bluefield". You will be asked to enter a new password once you connect to the UEFI menu. Resetting the password is highly recommended as UEFI secure boot could be easily disabled from UEFI menu by deleting the PK key certificate from the UEFI database. This requires access to the BlueField console, however.
It is possible to override all the key certificate files of the UEFI database. This allows you to enroll your PK key certificate, your KEK key certificate, and your db certificates. This requires UEFI secure boot to be disabled. To disable UEFI secure boot temporarily, reboot the platform and stop at the UEFI menu. From the UEFI menu screen, select "Device Manager", then "Secure Boot Configuration". If "Attempt Secure Boot" is checked, then uncheck it and reboot.
To enroll your key certificates, create a capsule file by way of tools and scripts provided along with the BlueField software distribution (BSD). In the following example, BSD version 3.6.0.11691 is used.
To install the BSD package, download the tarball file and unpack it within the working area:
$ tar xvf BlueField-3.6.0.11691.tar.xz
To create the capsule files, execute the "mlx-mkcap" script located in the BSD under boot/capsules/scripts. This script generates a capsule file to supply the key certificates to UEFI and enable UEFI secure boot:
$ ./mlx-mkcap --pk-key pk.cer --kek-key kek.cer --db-key db.cer EnrollYourKeysCap
Note that you may specify as many db certificates as needed using the --db-key command option. You may add NVIDIA db certificate files and Microsoft certificate file, if needed. In this example, only a single db certificate is specified.
To set the UEFI password, you may specify the --uefi-passwd option. For example, to set the UEFI password to “bluefield”, run the following command:
$ ./mlx-mkcap --pk-key pk.cer --kek-key kek.cer --db-key db.cer --uefi-passwd "bluefield" EnrollYourKeysCap
The resulting capsule file "EnrollYourKeysCap" can be downloaded to the BlueField file system to initiate the key enrollment process. From the the BlueField console execute the following command then reboot:
ubuntu@localhost:~$ bfrec --capsule EnrollYourKeysCap
On the next reboot, the capsule file is processed and the UEFI database is populated with the keys extracted from the capsule file. Note that enrolling the PK key certificate file enables the UEFI secure boot.
Update Key Certificates
While UEFI secure boot is enabled, it is possible to update your keys using a capsule file. This requires UEFI secure boot to have been enabled using your own keys, which means that you own the signing keys.
To create a capsule intended to update the UEFI secure boot keys, generate the new set of keys, and then run:
$ ./mlx-mkcap --pk-key new_pk.cer --kek-key new_kek.cer --db-key new_db1.cer --db-key new_db2.cer --db-key new_db3.cer --signer-key db.key --signer-cert db.pem EnrollYourNewKeysCap
Note that --signer-key and --signer-cert are set so the capsule is signed. When UEFI secure boot is enabled, the capsule is verified using the key certificates previously enrolled in the UEFI database. It is important to use the old signing keys associated with the certificates in the UEFI database to sign the capsule. The new key certificates are intended to replace the existing key certificates after the capsule processing. Once the UEFI database is updated, the new keys must be used to sign the newly created capsule files.
To enroll the new set of keys, download the capsule file to the BlueField console and use bfrec to initiate the capsule update.
Disable UEFI Secure Boot
It is also possible to disable UEFI secure boot through capsule update. This requires an empty PK key when creating the capsule file.
To create a capsule intended to disable UEFI secure boot, create a dummy empty PK certificate:
$ touch null_pk.cer
Then create the capsule file:
$ ./mlx-mkcap --pk-key null_pk.cer --signer-key db.key --signer-cert db.pem DeletePkCap
Note that --signer-key and --signer-cert must be specified with the appropriate private keys and certificates associated with the actual key certificates in the UEFI database.
To enroll the empty PK certificate, download the capsule file to the BlueField console and use bfrec to initiate the capsule update.
Deleting the PK certificate will result in the UEFI secure boot to be disabled.
Signing binaries for UEFI secure boot is complex as yous must create X.509 certificates and enroll them in UEFI or shim which requires a fair amount of prior knowledge of how secure boot works. For that reason, the processes used to enroll keys and to sign UEFI binaries are available in this document.
You might want to execute a UEFI application, a UEFI driver, an OS loader, a custom kernel, or load a custom module. Secure booting those binaries depends on what is available in the UEFI database and the shim MOK list.
If you previously enabled UEFI secure boot using your own key certificate files then you can use one of the signing keys associated with one of the db certificates in the UEFI database to sign your binary. Otherwise, you must create an X.509 certificate that can be imported either directly though the UEFI or, more easily, via shim.
Method |
Pros |
Cons |
Shim – |
Easy |
Very limited flexibility. Only allows executing a custom kernel or load a custom module. It does not allow executing UEFI applications, UEFI drivers or OS loaders. |
Does not require access to the BlueField console |
Dependency on Microsoft or NVIDIA as signing entities |
|
UEFI – |
Autonomy, as you control your keys (not dependent on Microsoft or NVIDIA as signing entities) |
You must manually add your key certificate to database |
Requires access to BlueField console (i.e., UART console required) |
Creating a certificate for use in UEFI Secure Boot is relatively simple. OpenSSL can do it by running the command req.
For illustration purposes, this example shows how to create a 2048-bit RSA MOK key and its associated certificate file in DER format.
$ openssl req -new -x509 -newkey rsa:2048 -nodes -days 36500 -outform DER -keyout "mok.priv" -out "mok.der"
An OpenSSL configuration file may be used for key generation. It may be specified using --config path/to/openssl.cnf.
Key and certificate generation are beyond the scope of this document.
In the following sections we refer to the db private key as "key.priv" and its DER certificate as "cert.der". Similarly, the MOK private key is referred to as "mok.priv" and its DER certificate as "mok.der".
Enrolling MOK Key
To boot a custom kernel or load a custom module, you will need to create a MOK key pair. The newly created MOK key must be an RSA 2048-bit. The private part is used for signing operations and must be kept safe. The public part X.509 key certificate in DER format must be enrolled within the shim MOK list.
Once the public key certificate is enrolled within the shim, the MOK key will be accepted as a valid signing key.
Note that kernel module signing requires a special configuration. For example, the extendedKeyUsage field must show an OID of 1.3.6.1.4.1.2312.16.1.2. That OID will tell shim that this is meant to be a module signing certificate.
For illustration purposes, an example of openssl configuration file is provided below:
HOME = .
RANDFILE = $ENV::HOME/.rnd
[ req ]
distinguished_name = req_distinguished_name
x509_extensions = v3
string_mask = utf8only
prompt = no
[ req_distinguished_name ]
countryName = US
stateOrProvinceName = Westborough
localityName = Massachusetts
0.organizationName = CampanyX
commonName = Secure Boot Signing
emailAddress = example@example.com
[ v3 ]
subjectKeyIdentifier = hash
authorityKeyIdentifier = keyid:always,issuer
basicConstraints = critical,CA:FALSE
extendedKeyUsage = codeSigning,1.3.6.1.4.1.311.10.3.6,1.3.6.1.4.1.2312.16.1.2
nsComment = "OpenSSL Generated Certificate"
To enroll the MOK key certificate, download the associated key certificate to the BlueField file system and run the following command:
ubuntu@localhost:~$ sudo mokutil --import mok.der
input password:
input password again:
You will need to follow the prompts to enter a password that will be used to make sure they really do want to enroll the key certificate.
Note that the key certificate is not enrolled yet. It will be enrolled by the Shim on the next reboot. To list the imported certificate file intended to be enrolled:
ubuntu@localhost:~$ sudo mokutil --list-new
The reboot needs to be performed.
Just before loading GRUB, shim will show a blue screen which is actually another piece of the shim project called "MokManager". You can ignore the blue screen showing an error message. Press "OK" to enter the "Shim UEFI key management" screen.
Use that screen to select "Enroll MOK" and follow the menus to finish the enrolling process.
You may also look at some of the properties of the key you are trying to add to make sure it is indeed the right one using "View key". MokManager will ask for the same password you typed in earlier when running mokutil before reboot. MokManager will save the key and you will need to reboot again.
To list the enrolled certificate files, run the following command:
ubuntu@localhost:~$ sudo mokutil --list-enrolled
Enrolling Your Own Key
Some users may need to generate their own keys. For convenience, the processes used to enroll keys into UEFI db as well as to sign UEFI binaries are available in this document.
To execute your binaries while UEFI secure boot is enabled, you will need your own pair of private and public key certificates. The supported keys are RSA 2048-bit and ECDSA 384-bit.
The private part is used for signing operations and must be kept safe. The public part X.509 key certificate in DER format must be enrolled within the UEFI db.
The X.509 DER certificate file must be installed into the EFI System Partition (ESP). Download the certificate file to BlueFIeld file system and place it into the ESP:
ubuntu@localhost:~$ sudo cp path/to/cert.der /boot/efi/
Before you enroll your own key certificate, UEFI secure boot must be temporarily disabled. The UEFI databases cannot be updated when UEFI secure boot is enabled.
To disable temporarily UEFI secure boot, reboot the platform and stop at the UEFI menu. From the UEFI menu screen, select "Device Manager" entry, then "Secure Boot Configuration". If "Attempt Secure Boot" is checked then uncheck it. Otherwise, you might need to enable UEFI secure boot and populate the UEFI database using the capsule file /lib/firmware/mellanox/boot/capsule/EnrollKeysCap prior to this step. Please refer to the "UEFI secure boot" section for further information.
If the UEFI database was not previously populated then you will need to enroll the rest of the key certificates, i.e., the KEK certificate, the Microsoft certificate and the PK certificate. It is important to enroll the PK certificate at last as it turns on UEFI secure boot.
Now to enroll the certificate into the UEFI db, you will need to reboot and login again into the UEFI menu. From the "UEFI menu", select "Device Manager" entry, then "Secure Boot Configuration". Select "Secure Boot Mode" and choose "Custom Mode" setup. The secure boot "Custom Mode" setup feature allows a physically present user to modify the UEFI database.
Once the platform is in "Custom Mode", a "Custom Secure Boot Options" menu entry appears which allows you to manipulate the UEFI database keys and certificates.
To enroll your DER certificate file, select "DB Options" and enter the "Enroll Signature" menu. Select "Enroll Signature Using File" and navigate within the EFI System Partition (ESP) to the db DER certificate file. The ESP path is shown below as "system-boot, [VenHw(*)/HD(*)]".
While enrolling the certificate file, you might enter a GUID along with the key certificate file. The GUID is the platform's way of identifying the key. It serves no purpose other than for you to tell which key is which when you delete them (it is not used at all in signature verification).
This value must be in the following format: 11111111-2222-3333-4444-1234567890ab.
If no value is entered, a GUID of 00000000-0000-0000-0000-000000000000 is created.
Finally, commit the changes and exit. You might be asked to reboot.
Signing Custom Kernel and UEFI Binaries
To sign a custom kernel or any other EFI binary (UEFI application, UEFI driver or OS loader) you want to have loaded by shim. You will require the private part of the key and the certificate in PEM format.
To convert the certificate into PEM, run:
$ openssl x509 -in mok.der -inform DER -outform PEM -out mok.pem
Now, to sign your EFI binary, run:
$ sbsign --key mok.priv --cert mok.pem binary.efi --output binary.efi.signed
Note that if you are using your db key, use the private part of the key and its associated certificate converted into PEM format for binary signing.
As long as the X.509 key certificate is enrolled in UEFI db or by way of shim, the binary should be loaded just fine.
Signing Kernel Modules
The X.509 certificate you added must be visible to the kernel. To verify the keys visible to the kernel, run:
ubuntu@localhost:~$ sudo cat /proc/keys
For a very straightforward result, run:
ubuntu@localhost:~$ dmesg | grep -i "X.509"
[ 1.869521] Loading compiled-in X.509 certificates
[ 1.875441] Loaded X.509 cert 'Build time autogenerated kernel key: b1a3fbd0178bdb7190387a4187e8e4b0eb476cdc'
[ 1.941752] integrity: Loading X.509 certificate: UEFI:db
[ 1.947636] integrity: Loaded X.509 cert 'YourSigningDbKey: a109f01707ba6769c4d546530ba1592c7daedc3b'
[ 1.958736] integrity: Loading X.509 certificate: UEFI:db
[ 1.964170] integrity: Loaded X.509 cert 'Microsoft Corporation UEFI CA 2011: 13adbf4309bd82709c8cd54f316ed522988a1bd4'
[ 2.023740] integrity: Loading X.509 certificate: UEFI:MokListRT
[ 2.030090] integrity: Loaded X.509 cert 'YourSingingMokKey: 2012e5122669ffc0cc28827c6134329a6bec0b88'
[ 2.040796] integrity: Loading X.509 certificate: UEFI:MokListRT
[ 2.046830] integrity: Loaded X.509 cert 'SomeOrg: shim: 331c1c8963538e327d6e39346f4f53b200987015'
[ 2.055796] integrity: Loading X.509 certificate: UEFI:MokListRT
[ 2.062114] integrity: Loaded X.509 cert 'Canonical Ltd. Master Certificate Authority: ad91990bc22ab1f517048c23b6655a268e345a63'
If the X.509 certificate attributes (commonName, etc.) are configured properly, you should see your key certificate information in the result output. In this example, two custom keys are visible to the kernel:
"YourSigningMokKey'' – registered with the Shim as a MOK
"YourSigningDbKey" – registered with UEFI as db
This example is for illustration purposes only. The actual output might differ from the output shown in this example depending on what key was previously enrolled and how it was enrolled.
You may sign kernel modules using either of these approaches:
Sign the kernel module using kmodsign command
Sign the kernel module using the Linux kernel script sign-file
Signing Kernel Modules Using kmodsign
If you are using the kmodsign command to sign kernel modules, run:
ubuntu@localhost:~$ kmodsign sha512 mok.priv mok.der module.ko module.ko
The signature will be appended to the kernel module by kmodsign.
But if you rather keep the original kernel module unchanged, run:
ubuntu@localhost:~$ kmodsign sha512 mok.priv mok.der module.ko module-signed.ko
See kmosign --help for more information.
Signing Kernel Modules Using sign-file
To sign the kernel module using the Linux kernel script sign-file, please refer to the Linux kernel documentation.
Note that if you are using your db key, use the private part of the key and its associated certificate for binary signing.
To validate that the module is signed, check that it includes the string "~Module signature appended~":
ubuntu@localhost:~$ hexdump -Cv module.ko | tail -n 5
00002c20 10 14 08 cd eb 67 a8 3d ac 82 e1 1d 46 b5 5c 91 |.....g.=....F.\.|
00002c30 9c cb 47 f7 c9 77 00 00 02 00 00 00 00 00 00 00 |..G..w..........|
00002c40 02 9e 7e 4d 6f 64 75 6c 65 20 73 69 67 6e 61 74 |..~Module signat|
00002c50 75 72 65 20 61 70 70 65 6e 64 65 64 7e 0a |ure appended~.|
00002c5e