lanzaboote: verify hash of kernel and initrd
This commit is contained in:
parent
7a15bba50b
commit
1739ffde26
|
@ -2,6 +2,18 @@
|
|||
# It is not intended for manual editing.
|
||||
version = 3
|
||||
|
||||
[[package]]
|
||||
name = "arrayref"
|
||||
version = "0.3.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a4c527152e37cf757a3f78aae5a06fbeefdb07ccc535c980a3208ee3060dd544"
|
||||
|
||||
[[package]]
|
||||
name = "arrayvec"
|
||||
version = "0.7.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8da52d66c7071e2e3fa2a1e5c6d088fec47b593032b254f5e980de8ea54454d6"
|
||||
|
||||
[[package]]
|
||||
name = "bit_field"
|
||||
version = "0.10.1"
|
||||
|
@ -14,12 +26,37 @@ version = "1.3.2"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
|
||||
|
||||
[[package]]
|
||||
name = "blake3"
|
||||
version = "1.3.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "42ae2468a89544a466886840aa467a25b766499f4f04bf7d9fcd10ecee9fccef"
|
||||
dependencies = [
|
||||
"arrayref",
|
||||
"arrayvec",
|
||||
"cc",
|
||||
"cfg-if",
|
||||
"constant_time_eq",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "cc"
|
||||
version = "1.0.77"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e9f73505338f7d905b19d18738976aae232eb46b8efc15554ffc56deb5d9ebe4"
|
||||
|
||||
[[package]]
|
||||
name = "cfg-if"
|
||||
version = "1.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
|
||||
|
||||
[[package]]
|
||||
name = "constant_time_eq"
|
||||
version = "0.2.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f3ad85c1f65dc7b37604eb0e89748faf0b9653065f2a8ef69f96a687ec1e9279"
|
||||
|
||||
[[package]]
|
||||
name = "ed25519-compact"
|
||||
version = "2.0.2"
|
||||
|
@ -41,6 +78,7 @@ dependencies = [
|
|||
name = "lanzaboote"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"blake3",
|
||||
"ed25519-compact",
|
||||
"goblin",
|
||||
"log",
|
||||
|
|
|
@ -11,6 +11,9 @@ log = "0.4.17"
|
|||
ed25519-compact = { version = "2.0.2", default-features = false, features = [] }
|
||||
goblin = { version = "0.6.0", default-features = false, features = [ "pe64", "alloc" ]}
|
||||
|
||||
# We don't want the assembly implementations for now.
|
||||
blake3 = { version = "1.3.3", default-features = false, features = [ "pure" ]}
|
||||
|
||||
[profile.release]
|
||||
opt-level = "s"
|
||||
lto = true
|
||||
|
|
|
@ -9,7 +9,8 @@ mod linux_loader;
|
|||
mod pe_section;
|
||||
mod uefi_helpers;
|
||||
|
||||
use pe_section::pe_section_as_string;
|
||||
use blake3::Hash;
|
||||
use pe_section::{pe_section, pe_section_as_string};
|
||||
use uefi::{
|
||||
prelude::*,
|
||||
proto::{
|
||||
|
@ -52,9 +53,33 @@ struct EmbeddedConfiguration {
|
|||
/// lanzaboote binary.
|
||||
kernel_filename: CString16,
|
||||
|
||||
/// The cryptographic hash of the kernel.
|
||||
kernel_hash: Hash,
|
||||
|
||||
/// The filename of the initrd to be passed to the kernel. See
|
||||
/// `kernel_filename` for how to interpret these filenames.
|
||||
initrd_filename: CString16,
|
||||
|
||||
/// The cryptographic hash of the initrd. This hash is computed
|
||||
/// over the whole PE binary, not only the embedded initrd.
|
||||
initrd_hash: Hash,
|
||||
}
|
||||
|
||||
/// Extract a filename from a PE section. The filename is stored as UTF-8.
|
||||
fn extract_filename(file_data: &[u8], section: &str) -> Result<CString16> {
|
||||
let filename = pe_section_as_string(file_data, section).ok_or(Status::INVALID_PARAMETER)?;
|
||||
|
||||
Ok(CString16::try_from(filename.as_str()).map_err(|_| Status::INVALID_PARAMETER)?)
|
||||
}
|
||||
|
||||
/// Extract a Blake3 hash from a PE section.
|
||||
fn extract_hash(file_data: &[u8], section: &str) -> Result<Hash> {
|
||||
let array: [u8; 32] = pe_section(file_data, section)
|
||||
.ok_or(Status::INVALID_PARAMETER)?
|
||||
.try_into()
|
||||
.map_err(|_| Status::INVALID_PARAMETER)?;
|
||||
|
||||
Ok(array.into())
|
||||
}
|
||||
|
||||
impl EmbeddedConfiguration {
|
||||
|
@ -62,14 +87,12 @@ impl EmbeddedConfiguration {
|
|||
file.set_position(0)?;
|
||||
let file_data = read_all(file)?;
|
||||
|
||||
let kernel_filename =
|
||||
pe_section_as_string(&file_data, ".kernelp").ok_or(Status::INVALID_PARAMETER)?;
|
||||
let initrd_filename =
|
||||
pe_section_as_string(&file_data, ".initrdp").ok_or(Status::INVALID_PARAMETER)?;
|
||||
|
||||
Ok(Self {
|
||||
kernel_filename: CString16::try_from(kernel_filename.as_str()).unwrap(),
|
||||
initrd_filename: CString16::try_from(initrd_filename.as_str()).unwrap(),
|
||||
kernel_filename: extract_filename(&file_data, ".kernelp")?,
|
||||
kernel_hash: extract_hash(&file_data, ".kernelh")?,
|
||||
|
||||
initrd_filename: extract_filename(&file_data, ".initrdp")?,
|
||||
initrd_hash: extract_hash(&file_data, ".initrdh")?,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
@ -121,6 +144,22 @@ fn main(handle: Handle, mut system_table: SystemTable<Boot>) -> Status {
|
|||
initrd_data = read_all(&mut initrd_file).expect("Failed to read kernel file into memory");
|
||||
}
|
||||
|
||||
if blake3::hash(&kernel_data) != config.kernel_hash {
|
||||
system_table
|
||||
.stdout()
|
||||
.output_string(cstr16!("Hash mismatch for kernel. Refusing to load!\r\n"))
|
||||
.unwrap();
|
||||
return Status::SECURITY_VIOLATION;
|
||||
}
|
||||
|
||||
if blake3::hash(&initrd_data) != config.initrd_hash {
|
||||
system_table
|
||||
.stdout()
|
||||
.output_string(cstr16!("Hash mismatch for initrd. Refusing to load!\r\n"))
|
||||
.unwrap();
|
||||
return Status::SECURITY_VIOLATION;
|
||||
}
|
||||
|
||||
let kernel_cmdline =
|
||||
booted_image_cmdline(system_table.boot_services()).expect("Failed to fetch command line");
|
||||
|
||||
|
|
Loading…
Reference in New Issue