Skip to content

Commit 9ba6517

Browse files
nicholasbishopGabrielMajeri
authored andcommitted
Add shim lock protocol
This protocol is not part of the UEFI specification, but is installed by the [Shim bootloader](https://github.com/rhboot/shim) which is commonly used by Linux distributions to support UEFI Secure Boot. Shim is built with an embedded certificate that is used to validate another EFI application before running it. That application may itself be a bootloader that needs to validate another EFI application before running it, and the shim lock protocol exists to support that.
1 parent 90e7839 commit 9ba6517

File tree

4 files changed

+62
-0
lines changed

4 files changed

+62
-0
lines changed

src/proto/mod.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,3 +32,4 @@ pub mod device_path;
3232
pub mod loaded_image;
3333
pub mod media;
3434
pub mod pi;
35+
pub mod shim;

src/proto/shim/mod.rs

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
//! Shim lock protocol.
2+
3+
use crate::proto::Protocol;
4+
use crate::result::Error;
5+
use crate::{unsafe_guid, Result, Status};
6+
use core::convert::TryInto;
7+
8+
/// The Shim lock protocol.
9+
///
10+
/// This protocol is not part of the UEFI specification, but is
11+
/// installed by the [Shim bootloader](https://github.com/rhboot/shim)
12+
/// which is commonly used by Linux distributions to support UEFI
13+
/// Secure Boot. Shim is built with an embedded certificate that is
14+
/// used to validate another EFI application before running it. That
15+
/// application may itself be a bootloader that needs to validate
16+
/// another EFI application before running it, and the shim lock
17+
/// protocol exists to support that.
18+
#[repr(C)]
19+
#[unsafe_guid("605dab50-e046-4300-abb6-3dd810dd8b23")]
20+
#[derive(Protocol)]
21+
pub struct ShimLock {
22+
verify: extern "efiapi" fn(buffer: *const u8, size: u32) -> Status,
23+
}
24+
25+
impl ShimLock {
26+
/// Verify that an EFI application is signed by the certificate
27+
/// embedded in shim.
28+
///
29+
/// The buffer's size must fit in a `u32`; if that condition is not
30+
/// met then a `BAD_BUFFER_SIZE` error will be returned and the shim
31+
/// lock protocol will not be called.
32+
pub fn verify(&self, buffer: &[u8]) -> Result {
33+
let size: u32 = buffer
34+
.len()
35+
.try_into()
36+
.map_err(|_| Error::from(Status::BAD_BUFFER_SIZE))?;
37+
(self.verify)(buffer.as_ptr(), size).into()
38+
}
39+
}

uefi-test-runner/src/proto/mod.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ pub fn test(st: &SystemTable<Boot>) {
1313
debug::test(bt);
1414
media::test(bt);
1515
pi::test(bt);
16+
shim::test(bt);
1617
}
1718

1819
fn find_protocol(bt: &BootServices) {
@@ -32,3 +33,4 @@ mod console;
3233
mod debug;
3334
mod media;
3435
mod pi;
36+
mod shim;

uefi-test-runner/src/proto/shim.rs

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
use uefi::proto::shim::ShimLock;
2+
use uefi::table::boot::BootServices;
3+
4+
pub fn test(bt: &BootServices) {
5+
info!("Running shim lock protocol test");
6+
7+
if let Ok(shim_lock) = bt.locate_protocol::<ShimLock>() {
8+
let shim_lock = shim_lock.expect("Warnings encountered while opening shim lock protocol");
9+
let shim_lock = unsafe { &*shim_lock.get() };
10+
11+
// An empty buffer should definitely be invalid, so expect
12+
// shim to reject it.
13+
let buffer = [];
14+
shim_lock
15+
.verify(&buffer)
16+
.expect_err("shim failed to reject an invalid application");
17+
} else {
18+
info!("Shim lock protocol is not supported");
19+
}
20+
}

0 commit comments

Comments
 (0)