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

certs: Adding additional functionality. #206

Merged
merged 1 commit into from
Jul 31, 2024
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 Cargo.lock

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

2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "sev"
version = "3.2.0"
version = "3.3.0"
authors = [
"Nathaniel McCallum <[email protected]>",
"The VirTEE Project Developers",
Expand Down
73 changes: 73 additions & 0 deletions src/certs/snp/ca/mod.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
// SPDX-License-Identifier: Apache-2.0
#[cfg(feature = "openssl")]
use openssl::x509::X509;

use super::*;

Expand Down Expand Up @@ -29,6 +31,77 @@ impl<'a> Verifiable for &'a Chain {
}
}

#[cfg(feature = "openssl")]
impl From<(X509, X509)> for Chain {
Copy link
Member

Choose a reason for hiding this comment

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

I think the ordering of the tuples/arrays/etc should be ARK/ASK rather than ASK/ARK.

Copy link
Contributor Author

@larrydewey larrydewey Jul 30, 2024

Choose a reason for hiding this comment

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

I don't disagree. I would like the root key first, as well. However, we need to follow the standard already presented by the AMD Key Distribution Server (KDS) which explicitly returns (ASK, ARK) in PEM format:

https://www.amd.com/content/dam/amd/en/documents/epyc-technical-docs/specifications/57230.pdf#page=17

/// Assumes the structure of ASK/ARK or ASVK/ARK
fn from(value: (X509, X509)) -> Self {
Self {
ark: value.1.into(),
ask: value.0.into(),
}
}
}

#[cfg(feature = "openssl")]
impl From<(&X509, &X509)> for Chain {
/// Assumes the structure of &ASK/&ARK or &ASVK/&ARK
fn from(value: (&X509, &X509)) -> Self {
(value.0.clone(), value.1.clone()).into()
}
}

#[cfg(feature = "openssl")]
impl<'a: 'b, 'b> From<&'a Chain> for (&'b X509, &'b X509) {
/// Will always assume the tuple type to be (&ASK, &ARK) or (&ASVK, &ARK).
fn from(value: &'a Chain) -> Self {
((&value.ask).into(), (&value.ark).into())
}
}

#[cfg(feature = "openssl")]
impl From<&[X509]> for Chain {
/// Will only retrieve the first two certificates, ignoring the rest. Also
/// assumes the structure to be (&ASK, &ARK) or (&ASVK, &ARK)
fn from(value: &[X509]) -> Self {
(&value[0], &value[1]).into()
}
}

impl From<(Certificate, Certificate)> for Chain {
/// Assumes the structure of ASK/ARK or ASVK/ARK
fn from(value: (Certificate, Certificate)) -> Self {
Self {
ark: value.1,
ask: value.0,
}
}
}

impl From<(&Certificate, &Certificate)> for Chain {
/// Assumes the structure of &ASK/&ARK or &ASVK/&ARK
fn from(value: (&Certificate, &Certificate)) -> Self {
Self {
ark: value.1.clone(),
ask: value.0.clone(),
}
}
}

impl<'a: 'b, 'b> From<&'a Chain> for (&'b Certificate, &'b Certificate) {
/// Will always assume the tuple type to be (&ASK, &ARK) or (&ASVK, &ARK).
fn from(value: &'a Chain) -> Self {
(&value.ask, &value.ark)
}
}

impl From<&[Certificate]> for Chain {
/// Will only retrieve the first two certificates, ignoring the rest. Also
/// assumes the structure to be (&ASK, &ARK) or (&ASVK, &ARK)
fn from(value: &[Certificate]) -> Self {
(&value[0], &value[1]).into()
}
}

impl Chain {
/// Deserialize a PEM-encoded ARK and ASK pair to a CA chain.
pub fn from_pem(ark: &[u8], ask: &[u8]) -> Result<Self> {
Expand Down
19 changes: 19 additions & 0 deletions src/certs/snp/cert.rs
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,25 @@ impl From<&Certificate> for X509 {
}
}

impl From<&X509> for Certificate {
fn from(value: &X509) -> Self {
Self(value.clone())
}
}

impl From<&[X509]> for Certificate {
/// Retrieves only the first value from the hash, ignoring all other values.
fn from(value: &[X509]) -> Self {
value[0].clone().into()
}
}

impl<'a: 'b, 'b> From<&'a Certificate> for &'b X509 {
fn from(value: &'a Certificate) -> Self {
&value.0
}
}

/// Verify if the public key of one Certificate signs another Certificate.
impl Verifiable for (&Certificate, &Certificate) {
type Output = ();
Expand Down
86 changes: 86 additions & 0 deletions src/certs/snp/chain.rs
Original file line number Diff line number Diff line change
@@ -1,11 +1,15 @@
// SPDX-License-Identifier: Apache-2.0

#[cfg(feature = "openssl")]
use openssl::x509::X509;

use super::*;

use crate::firmware::host::{CertTableEntry, CertType};

/// Interfaces for a complete SEV-SNP certificate chain.

#[derive(Debug, Clone)]
pub struct Chain {
/// The Certificate Authority (CA) chain.
pub ca: ca::Chain,
Expand Down Expand Up @@ -37,6 +41,88 @@ enum ChainEncodingFormat {
Pem,
}

#[cfg(feature = "openssl")]
impl From<(X509, X509, X509)> for Chain {
/// Will presume the provided data is formated as (ASK,ARK,VCEK) or (ASVK,ARK,VLEK).
fn from(value: (X509, X509, X509)) -> Self {
Self {
ca: ca::Chain {
ark: value.1.into(),
ask: value.0.into(),
},
vek: value.2.into(),
}
}
}

#[cfg(feature = "openssl")]
impl<'a: 'b, 'b> From<&'a Chain> for (&'b X509, &'b X509, &'b X509) {
/// Will presume the provided data is formated as (ASK,ARK,VCEK) or (ASVK,ARK,VLEK).
fn from(value: &'a Chain) -> Self {
(
(&value.ca.ask).into(),
(&value.ca.ark).into(),
(&value.vek).into(),
)
}
}

#[cfg(feature = "openssl")]
impl From<(&X509, &X509, &X509)> for Chain {
fn from(value: (&X509, &X509, &X509)) -> Self {
(value.0.clone(), value.1.clone(), value.2.clone()).into()
}
}

impl<'a: 'b, 'b> From<&'a Chain> for (&'b Certificate, &'b Certificate, &'b Certificate) {
fn from(value: &'a Chain) -> Self {
(&value.ca.ask, &value.ca.ark, &value.vek)
}
}

impl From<(Certificate, Certificate, Certificate)> for Chain {
fn from(value: (Certificate, Certificate, Certificate)) -> Self {
Self {
ca: ca::Chain {
ark: value.1,
ask: value.0,
},
vek: value.2,
}
}
}

impl From<(&Certificate, &Certificate, &Certificate)> for Chain {
fn from(value: (&Certificate, &Certificate, &Certificate)) -> Self {
Self {
ca: ca::Chain {
ark: value.1.clone(),
ask: value.0.clone(),
},
vek: value.2.clone(),
}
}
}

impl From<&Chain> for (Certificate, Certificate, Certificate) {
/// Will presume the user wants the format of (ASK,ARK,VCEK) or (ASVK,ARK,VLEK).
fn from(value: &Chain) -> Self {
(
value.ca.ask.clone(),
value.ca.ark.clone(),
value.vek.clone(),
)
}
}

impl From<&[Certificate]> for Chain {
/// Assumes the Format of ASK/ARK/VCEK or ASVK/ARK/VLEK. Any additional
/// certificates are ignored.
fn from(value: &[Certificate]) -> Self {
(value[0].clone(), value[1].clone(), value[2].clone()).into()
}
}

impl Chain {
/// Derive a chain from a DER-encoded FFI Certificate table.
pub fn from_cert_table_der(entries: Vec<CertTableEntry>) -> Result<Self> {
Expand Down