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.
|
# It is not intended for manual editing.
|
||||||
version = 3
|
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]]
|
[[package]]
|
||||||
name = "bit_field"
|
name = "bit_field"
|
||||||
version = "0.10.1"
|
version = "0.10.1"
|
||||||
|
@ -14,12 +26,37 @@ version = "1.3.2"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
|
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]]
|
[[package]]
|
||||||
name = "cfg-if"
|
name = "cfg-if"
|
||||||
version = "1.0.0"
|
version = "1.0.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
|
checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "constant_time_eq"
|
||||||
|
version = "0.2.4"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "f3ad85c1f65dc7b37604eb0e89748faf0b9653065f2a8ef69f96a687ec1e9279"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "ed25519-compact"
|
name = "ed25519-compact"
|
||||||
version = "2.0.2"
|
version = "2.0.2"
|
||||||
|
@ -41,6 +78,7 @@ dependencies = [
|
||||||
name = "lanzaboote"
|
name = "lanzaboote"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
|
"blake3",
|
||||||
"ed25519-compact",
|
"ed25519-compact",
|
||||||
"goblin",
|
"goblin",
|
||||||
"log",
|
"log",
|
||||||
|
|
|
@ -11,6 +11,9 @@ log = "0.4.17"
|
||||||
ed25519-compact = { version = "2.0.2", default-features = false, features = [] }
|
ed25519-compact = { version = "2.0.2", default-features = false, features = [] }
|
||||||
goblin = { version = "0.6.0", default-features = false, features = [ "pe64", "alloc" ]}
|
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]
|
[profile.release]
|
||||||
opt-level = "s"
|
opt-level = "s"
|
||||||
lto = true
|
lto = true
|
||||||
|
|
|
@ -9,7 +9,8 @@ mod linux_loader;
|
||||||
mod pe_section;
|
mod pe_section;
|
||||||
mod uefi_helpers;
|
mod uefi_helpers;
|
||||||
|
|
||||||
use pe_section::pe_section_as_string;
|
use blake3::Hash;
|
||||||
|
use pe_section::{pe_section, pe_section_as_string};
|
||||||
use uefi::{
|
use uefi::{
|
||||||
prelude::*,
|
prelude::*,
|
||||||
proto::{
|
proto::{
|
||||||
|
@ -52,9 +53,33 @@ struct EmbeddedConfiguration {
|
||||||
/// lanzaboote binary.
|
/// lanzaboote binary.
|
||||||
kernel_filename: CString16,
|
kernel_filename: CString16,
|
||||||
|
|
||||||
|
/// The cryptographic hash of the kernel.
|
||||||
|
kernel_hash: Hash,
|
||||||
|
|
||||||
/// The filename of the initrd to be passed to the kernel. See
|
/// The filename of the initrd to be passed to the kernel. See
|
||||||
/// `kernel_filename` for how to interpret these filenames.
|
/// `kernel_filename` for how to interpret these filenames.
|
||||||
initrd_filename: CString16,
|
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 {
|
impl EmbeddedConfiguration {
|
||||||
|
@ -62,14 +87,12 @@ impl EmbeddedConfiguration {
|
||||||
file.set_position(0)?;
|
file.set_position(0)?;
|
||||||
let file_data = read_all(file)?;
|
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 {
|
Ok(Self {
|
||||||
kernel_filename: CString16::try_from(kernel_filename.as_str()).unwrap(),
|
kernel_filename: extract_filename(&file_data, ".kernelp")?,
|
||||||
initrd_filename: CString16::try_from(initrd_filename.as_str()).unwrap(),
|
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");
|
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 =
|
let kernel_cmdline =
|
||||||
booted_image_cmdline(system_table.boot_services()).expect("Failed to fetch command line");
|
booted_image_cmdline(system_table.boot_services()).expect("Failed to fetch command line");
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue