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

verifier: Fetch VCEK cert from KDS instead of bailing #555

Open
wants to merge 3 commits into
base: main
Choose a base branch
from

Conversation

AdithyaKrishnan
Copy link

Fetch the VCEK cert from the KDS if it is absent in the cert chain instead of just printing a bail statement stating that the VCEK is not found.

Fetch the VCEK cert from the KDS if it is absent in the cert chain instead of just printing a bail statement stating that the VCEK is not found.

Signed-off-by: Adithya Krishnan Kannan <[email protected]>
@AdithyaKrishnan AdithyaKrishnan requested a review from a team as a code owner November 4, 2024 18:17
Copy link

@cclaudio cclaudio left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just a few minor comments.

// Function to request vcek from KDS. Return vcek in der format.
fn request_endorsement_key_kds(
att_report: AttestationReport,
) -> Result<Vec<CertTableEntry>, anyhow::Error> {
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The function is specific to download the VCEK, so I think it could be rename to something more specific such as fetch_vcek_from_kds()

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Additionally, I think the function would be more self-contained if it returns Result<Vec<u8>>

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Changed. If appropriate, please mark this comment as Resolved.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Additionally, I think the function would be more self-contained if it returns Result<Vec<u8>>

Tried this and got a type mismatch error

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Btw I don't think you need anyhow::Error in in this return type.

Copy link
Member

@fitzthum fitzthum left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice PR. Looks like this will address #456 which is actually a duplicate of #363

One thing to think about is that this could result in quite a few requests being made to the KDS. We should probably implement some kind of caching mechanism so that the verifier doesn't have to get the vcek for the same node again and again. We can probably do this in a follow-up.

Also, we might want to add vlek support at some point although I suspect this will require specifying a few more config params.

@@ -49,6 +49,7 @@ strum.workspace = true
veraison-apiclient = { git = "https://github.com/chendave/rust-apiclient", branch = "token", optional = true }
ear = { git = "https://github.com/veraison/rust-ear", rev = "43f7f480d09ea2ebc03137af8fbcd70fe3df3468", optional = true }
x509-parser = { version = "0.14.0", optional = true }
reqwest = { version="0.12.9", features = ["blocking"] }
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I you are already specifying the needed version of reqwest in the global Cargo file, you can just say request = workspace.true here.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Changed. If appropriate, please mark this comment as Resolved.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

See Ding's suggestions about the Cargo file as well.

@@ -84,8 +85,10 @@ impl Verifier for Snp {
cert_chain,
} = serde_json::from_slice(evidence).context("Deserialize Quote failed.")?;

let Some(cert_chain) = cert_chain else {
bail!("Cert chain is unset");
let cert_chain = if let Some(chain) = cert_chain{
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So the cert chain is type Option<Vec<Cert>> or something. This accounts for cases where the option is none, but what if the option is there but the vector is empty?

Ideally we should get the vcek even if there is a non-empty cert chain as long as the vcek/vlek isn't part of it.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could this be part of the future follow-up PR?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We can leave check the cert types to a follow-up, but please add a case to this statement to catch an empty vector.

deps/verifier/src/snp/mod.rs Outdated Show resolved Hide resolved
) -> Result<Vec<CertTableEntry>, anyhow::Error> {
// KDS URL parameters
const KDS_CERT_SITE: &str = "https://kdsintf.amd.com";
const KDS_VCEK: &str = "/vcek/v1";
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

might be better to put these consts at the top of the file rather than inside this function

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed. If appropriate, please mark this comment as Resolved.

StatusCode::OK => {
let vcek_rsp_bytes: Vec<u8> =
vcek_rsp.bytes().context("Unable to parse VCEK")?.to_vec();
let key= CertTableEntry{cert_type: CertType::VCEK, data: vcek_rsp_bytes};
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: key= -> key =. Also you probably want some spaces around the {. I'm surprised this survived cargo fmt check.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If appropriate, please mark this comment as Resolved.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

there are more formatting/lint issues. we do have a problem in the build pipeline, the verifier crate is not linted/formatted.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can you run

cargo fmt
cargo clippy -p verifier -- -D warnings

on your code in the mean time and fix the warnings?

Cargo.lock Outdated
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It seems your Cargo.lock has more changes than required. You may need to restore it and apply the request = worspace.true change that Tobin suggested

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If appropriate, please mark this comment as Resolved.

1. In deps\verifier\src\snp\mod.rs:

i. Rename function request_endorsement_key_kds() -> fetch_vcek_from_kds()
ii. KDS URL Parameter consts shifted to top of file
iii. Corrected spacing around key and curly baces in vcek_rsp.status() match

2. In deps/verifier/Cargo.toml
i. set reqwest = workspace.true

Signed-off-by: Adithya Krishnan Kannan <[email protected]>
@@ -482,4 +518,4 @@ mod tests {
let vendor_certs = load_milan_cert_chain().as_ref().unwrap();
verify_report_signature(&attestation_report, &cert_chain, vendor_certs).unwrap_err();
}
}
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this empty line can be reserved

@@ -36,7 +36,7 @@ jsonwebtoken = { version = "9", default-features = false }
log = "0.4.17"
prost = "0.12"
regorus = { version = "0.1.5", default-features = false, features = ["regex", "base64", "time"] }
reqwest = { version = "0.12", default-features = false, features = ["default-tls"] }
reqwest = { version = "0.12", default-features = false, features = ["default-tls", "blocking"] }
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I noticed that the reqwest is used in fetch_vcek_from_kds. It is suggested to use reqwest::get (the async version) rather than blocking version, because the blocking version would hang on network I/O during which the process would wait.

deps/verifier/Cargo.toml Outdated Show resolved Hide resolved
let key = CertTableEntry { cert_type: CertType::VCEK, data: vcek_rsp_bytes };
Ok(vec![key])
}
status => Err(anyhow::anyhow!("Unable to fetch VCEK from URL: {status:?}")),
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

anyhow::anyhow! -> anyhow!

Co-authored-by: Xynnn_ <[email protected]>
Signed-off-by: Adithya Krishnan Kannan <[email protected]>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants