Skip to content

Commit

Permalink
Add and verify endorsement field for text reference value (#4973)
Browse files Browse the repository at this point in the history
The kernel command line reference value now follows the pattern from other reference values: skip, TR endorsement, or direct verification. When using TR endorsements in conjunction with the kernel command line the regex feature needs to be enabled.
  • Loading branch information
thmsbinder authored Apr 3, 2024
1 parent fa50670 commit 4ad534f
Show file tree
Hide file tree
Showing 2 changed files with 37 additions and 14 deletions.
41 changes: 30 additions & 11 deletions oak_attestation_verification/src/verifier.rs
Original file line number Diff line number Diff line change
Expand Up @@ -520,11 +520,13 @@ fn verify_kernel_layer(

if let Some(kernel_raw_cmd_line) = values.kernel_raw_cmd_line.as_ref() {
verify_text(
now_utc_millis,
kernel_raw_cmd_line.as_str(),
reference_values
.kernel_cmd_line_text
.as_ref()
.context("no kernel command line text reference values")?,
endorsements.and_then(|value| value.kernel_cmd_line.as_ref()),
)
.context("kernel command line failed verification")?;
} else {
Expand Down Expand Up @@ -761,10 +763,33 @@ fn verify_hex_digests(actual: &HexDigest, expected: &HexDigest) -> anyhow::Resul
}
}

fn verify_text(actual: &str, expected: &TextReferenceValue) -> anyhow::Result<()> {
fn verify_text(
now_utc_millis: i64,
actual: &str,
expected: &TextReferenceValue,
endorsement: Option<&TransparentReleaseEndorsement>,
) -> anyhow::Result<()> {
match expected.r#type.as_ref() {
Some(text_reference_value::Type::Skip(_)) => Ok(()),
Some(text_reference_value::Type::Regex(regex)) => verify_regex(actual, regex),
Some(text_reference_value::Type::Endorsement(public_keys)) => {
let endorsement =
endorsement.context("matching endorsement not found for text reference value")?;
verify_binary_endorsement(
now_utc_millis,
&endorsement.endorsement,
&endorsement.endorsement_signature,
&endorsement.rekor_log_entry,
&public_keys.endorser_public_key,
&public_keys.rekor_public_key,
)?;
// Compare the actual command line against the one inlined in the endorsement.
let regex = String::from_utf8(endorsement.subject.clone())
.expect("endorsement subject is not utf8");
verify_regex(actual, &regex).context("regex from endorsement does not match")
}
Some(text_reference_value::Type::Regex(regex)) => {
verify_regex(actual, &regex.value).context("regex from reference values does not match")
}
Some(text_reference_value::Type::StringLiterals(string_literals)) => {
anyhow::ensure!(!string_literals.value.is_empty());
for sl in string_literals.value.iter() {
Expand All @@ -781,11 +806,8 @@ fn verify_text(actual: &str, expected: &TextReferenceValue) -> anyhow::Result<()
}

#[cfg(feature = "regex")]
fn verify_regex(
actual: &str,
regex: &oak_proto_rust::oak::attestation::v1::Regex,
) -> anyhow::Result<()> {
let re = Regex::new(regex.value.as_str())
fn verify_regex(actual: &str, regex: &str) -> anyhow::Result<()> {
let re = Regex::new(regex)
.map_err(|msg| anyhow::anyhow!("couldn't parse regex in the reference value: {msg}"))?;
Ok(anyhow::ensure!(
re.is_match(actual),
Expand All @@ -794,10 +816,7 @@ fn verify_regex(
}

#[cfg(not(feature = "regex"))]
fn verify_regex(
_actual: &str,
_regex: &oak_proto_rust::oak::attestation::v1::Regex,
) -> anyhow::Result<()> {
fn verify_regex(_actual: &str, _regex: &str) -> anyhow::Result<()> {
Err(anyhow::anyhow!("verification of regex values not supported"))
}

Expand Down
10 changes: 7 additions & 3 deletions proto/attestation/reference_value.proto
Original file line number Diff line number Diff line change
Expand Up @@ -97,8 +97,8 @@ message Regex {
string value = 1;
}

// A match in at least onevalue is considered a success. At least one value must
// be specified, otherwise verification fails.
// A match in at least one value is considered a success. At least one value
// must be specified, otherwise verification fails.
message StringLiterals {
repeated string value = 1;
}
Expand All @@ -113,9 +113,12 @@ message RegexReferenceValue {
}
}

// Reference value to match text via endorsement, or directly via constants
// or a regular expression.
message TextReferenceValue {
oneof type {
SkipVerification skip = 1;
EndorsementReferenceValue endorsement = 4;
Regex regex = 2;
StringLiterals string_literals = 3;
}
Expand Down Expand Up @@ -159,7 +162,8 @@ message KernelLayerReferenceValues {
// Verifies the kernel based on endorsement.
KernelBinaryReferenceValue kernel = 1;

// Validates the kernel command-line using either a string literal or a regex.
// Verifies the kernel command line, i.e. the parameters passed to the
// kernel on boot.
TextReferenceValue kernel_cmd_line_text = 9;

// Fields are deprecated and kept only for backwards compatibility. They are
Expand Down

0 comments on commit 4ad534f

Please sign in to comment.