Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

RFC: Adding Measurement functionality to library #110

Merged
merged 3 commits into from
Nov 8, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .gitignore
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
/target
.vscode/
.vscode/
1 change: 1 addition & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 2 additions & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -66,8 +66,9 @@ p384 = { version = "0.13.0", optional = true }
rsa = { version = "0.9.2", optional = true }
sha2 = { version = "0.10.8", optional = true }
x509-cert = { version = "0.2.4", optional = true }
byteorder = "1.4.3"

[dev-dependencies]
kvm-ioctls = ">=0.12"
kvm-bindings = ">=0.6"
serial_test = "2.0"
serial_test = "2.0"
249 changes: 249 additions & 0 deletions src/error.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
// SPDX-License-Identifier: Apache-2.0

use bincode;
use std::{
array::TryFromSliceError,
convert::From,
error,
fmt::{Debug, Display},
Expand Down Expand Up @@ -595,3 +597,250 @@ impl From<Indeterminate<Error>> for c_int {
}
}
}

#[derive(Debug)]
/// Errors which may be encountered when building custom guest context.
pub enum GCTXError {
/// Malformed guest context page.
InvalidPageSize(usize, usize),

/// Block size data was the incorrect size
InvalidBlockSize,

/// Missing data to do page update
MissingData,

/// Missing block size
MissingBlockSize,

/// Unknown Error.
UnknownError,
}

impl std::fmt::Display for GCTXError {
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
match self {
GCTXError::InvalidPageSize(actual, expected) => write!(
f,
"Page information was not the correct length ({actual} vs {expected})"
),
GCTXError::InvalidBlockSize => {
write!(f, "Provided data does not conform to a 4096 block size")
}
GCTXError::MissingData => {
write!(f, "Did not provide data to perform page update")
}
GCTXError::MissingBlockSize => {
write!(f, "Did not provide block size to perform page update")
}
GCTXError::UnknownError => write!(f, "An unknown Guest Context error encountered"),
}
}
}

impl std::error::Error for GCTXError {}

#[derive(Debug)]
/// Errors which may be encountered when handling OVMF data
pub enum OVMFError {
/// An invalid section type was provided for OVMF METADATA
InvalidSectionType,

/// Part of the SEV METADATA failed verification
SEVMetadataVerification(String),

/// Desired entry is missing from table
EntryMissingInTable(String),

/// Failed to get item from table
GetTableItemError,

/// Invalid Entry Size was provided
InvalidSize(String, usize, usize),

/// GUID doesn't match expected GUID
MismatchingGUID,

/// Unknown Error.
UnknownError,
}

impl std::fmt::Display for OVMFError {
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
match self {
OVMFError::InvalidSectionType => write!(f, "An invalid section type was found"),
OVMFError::SEVMetadataVerification(section) => {
write!(f, "Wrong SEV metadata {section}")
}
OVMFError::EntryMissingInTable(entry) => {
write!(f, "Can't find {entry} entry in OVMF table")
}
OVMFError::GetTableItemError => {
write!(f, "OVMF table failed to return item")
}
OVMFError::InvalidSize(entry, actual, expected) => {
write!(f, "Invalid size of {entry}: {actual} < {expected}")
}
OVMFError::MismatchingGUID => {
write!(f, "OVMF table footer GUID does not match expected GUID")
}
OVMFError::UnknownError => write!(f, "An unknown OVMF error encountered"),
}
}
}

impl std::error::Error for OVMFError {}

/// Errors which may be encountered when building SEV hashes.
DGonzalezVillal marked this conversation as resolved.
Show resolved Hide resolved
#[derive(Debug)]
pub enum SevHashError {
/// Provided page has invalid size
InvalidSize(usize, usize),

/// Provided page has invalid offset
InvalidOffset(usize, usize),

/// Unknown Error.
UnknownError,
}

impl std::fmt::Display for SevHashError {
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
match self {
SevHashError::InvalidOffset(actual, expected) => {
write!(f, "Invalid page Offset: {actual} vs {expected}")
}
SevHashError::InvalidSize(actual, expected) => {
write!(f, "Invalid page Size: {actual} vs {expected}")
}
SevHashError::UnknownError => write!(f, "An unknown SEV Hashing error encountered"),
}
}
}

impl std::error::Error for SevHashError {}

/// Errors which may be encountered when calculating the guest measurement.
DGonzalezVillal marked this conversation as resolved.
Show resolved Hide resolved
#[derive(Debug)]
pub enum MeasurementError {
/// TryFrom Slice Error handling
FromSliceError(TryFromSliceError),

/// UUID Error handling
UUIDError(uuid::Error),

/// Bincode Error Handling
BincodeError(bincode::ErrorKind),

/// File Error Handling
FileError(std::io::Error),

/// Vec from hex Error Handling
FromHexError(hex::FromHexError),

/// Guest Context Error Handling
GCTXError(GCTXError),

/// OVMF Error Handling
OVMFError(OVMFError),

/// SEV Hash Error Handling
SevHashError(SevHashError),

/// Invalid VCPU provided
InvalidVcpuTypeError(String),

/// Invalid VMM Provided
InvalidVmmError(String),

/// Invalid SEV Mode provided
InvalidSevModeError(String),

/// OVMF doesn't support kernel measurement
InvalidOvmfKernelError,

/// OVMF is missing required section with kernel specified
MissingSection(String),
}

impl std::fmt::Display for MeasurementError {
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
match self {
MeasurementError::FromSliceError(e) => write!(f, "Error converting slice: {e}"),
MeasurementError::UUIDError(e) => write!(f, "UUID Error encountered: {e}"),
MeasurementError::BincodeError(e) => write!(f, "Bincode error encountered: {e}"),
MeasurementError::FileError(e) => write!(f, "Failed handling file: {e}"),
MeasurementError::FromHexError(e) => write!(f, "Converting hex to vector error: {e}"),
MeasurementError::GCTXError(e) => write!(f, "GCTX Error Encountered: {e}"),
MeasurementError::OVMFError(e) => write!(f, "OVMF Error Encountered: {e}"),
MeasurementError::SevHashError(e) => write!(f, "Sev hash Error Encountered: {e}"),
MeasurementError::InvalidVcpuTypeError(value) => {
write!(f, "Invalid VCPU type value provided: {value}")
}
MeasurementError::InvalidVmmError(value) => {
write!(f, "Invalid VMM type provided: {value}")
}
MeasurementError::InvalidSevModeError(value) => {
write!(f, "Invalid SEV mode provided: {value}")
}
MeasurementError::InvalidOvmfKernelError => write!(
f,
"Kernel specified but OVMF doesn't support kernel/initrd/cmdline measurement"
),
MeasurementError::MissingSection(section) => write!(
f,
"Kernel specified but OVMF metadata doesn't include {section} section"
),
}
}
}

impl std::error::Error for MeasurementError {}

impl std::convert::From<TryFromSliceError> for MeasurementError {
fn from(value: TryFromSliceError) -> Self {
Self::FromSliceError(value)
}
}

impl std::convert::From<uuid::Error> for MeasurementError {
fn from(value: uuid::Error) -> Self {
Self::UUIDError(value)
}
}

impl std::convert::From<bincode::ErrorKind> for MeasurementError {
fn from(value: bincode::ErrorKind) -> Self {
Self::BincodeError(value)
}
}

impl std::convert::From<std::io::Error> for MeasurementError {
fn from(value: std::io::Error) -> Self {
Self::FileError(value)
}
}

impl std::convert::From<hex::FromHexError> for MeasurementError {
fn from(value: hex::FromHexError) -> Self {
Self::FromHexError(value)
}
}

impl std::convert::From<GCTXError> for MeasurementError {
fn from(value: GCTXError) -> Self {
Self::GCTXError(value)
}
}

impl std::convert::From<OVMFError> for MeasurementError {
fn from(value: OVMFError) -> Self {
Self::OVMFError(value)
}
}

impl std::convert::From<SevHashError> for MeasurementError {
fn from(value: SevHashError) -> Self {
Self::SevHashError(value)
}
}
2 changes: 2 additions & 0 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,8 @@ pub mod certs;
pub mod firmware;
#[cfg(target_os = "linux")]
pub mod launch;
#[cfg(all(any(feature = "sev", feature = "snp"), feature = "openssl"))]
larrydewey marked this conversation as resolved.
Show resolved Hide resolved
pub mod measurement;
#[cfg(all(target_os = "linux", feature = "openssl", feature = "sev"))]
pub mod session;
mod util;
Expand Down
Loading
Loading