From 89af1f578fb65f15d84a58132893adf63a0580e6 Mon Sep 17 00:00:00 2001 From: Larry Dewey Date: Mon, 12 Feb 2024 17:00:05 -0600 Subject: [PATCH] Certs: Adding generic support. Adding generic support to automatically identify which type of certificate the user provided and construct a Certificate from the identity discovered. Signed-off-by: Larry Dewey --- Cargo.toml | 1 + src/certs/snp/cert.rs | 61 +++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 62 insertions(+) diff --git a/Cargo.toml b/Cargo.toml index 15f41347..d922aecc 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -42,6 +42,7 @@ hw_tests = [] dangerous_hw_tests = ["hw_tests"] sev = [] snp = [] +openssl = ["dep:openssl"] crypto_nossl = ["dep:p384", "dep:rsa", "dep:sha2", "dep:x509-cert"] [target.'cfg(target_os = "linux")'.dependencies] diff --git a/src/certs/snp/cert.rs b/src/certs/snp/cert.rs index cde15420..5f04b120 100644 --- a/src/certs/snp/cert.rs +++ b/src/certs/snp/cert.rs @@ -10,6 +10,49 @@ use openssl::x509::X509; #[derive(Clone, Debug, Eq, PartialEq)] pub struct Certificate(X509); +#[derive(Clone, Copy, Debug, Eq, PartialEq)] +enum CertFormatError { + UnknownFormat, +} + +impl std::error::Error for CertFormatError {} + +impl std::fmt::Display for CertFormatError { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + match self { + Self::UnknownFormat => write!(f, "Unknown Certificate Format Encountered."), + } + } +} + +#[derive(Clone, Copy, Debug)] +enum CertFormat { + Pem, + Der, +} + +impl ToString for CertFormat { + fn to_string(&self) -> String { + match self { + Self::Pem => "pem", + Self::Der => "der", + } + .to_string() + } +} + +impl std::str::FromStr for CertFormat { + type Err = CertFormatError; + + fn from_str(s: &str) -> std::result::Result { + match s { + "pem" => Ok(Self::Pem), + "der" => Ok(Self::Der), + _ => Err(CertFormatError::UnknownFormat), + } + } +} + /// Wrap an X509 struct into a Certificate. impl From for Certificate { fn from(x509: X509) -> Self { @@ -77,4 +120,22 @@ impl Certificate { pub fn public_key(&self) -> Result> { Ok(self.0.public_key()?) } + + /// Identifies the format of a certificate based upon the first twenty-eight + /// bytes of a byte stream. A non-PEM format assumes DER format. + fn identify_format(bytes: &[u8]) -> CertFormat { + const PEM_START: &[u8] = b"-----BEGIN CERTIFICATE-----"; + match bytes { + PEM_START => CertFormat::Pem, + _ => CertFormat::Der, + } + } + + /// An façade method for constructing a Certificate from raw bytes. + pub fn from_bytes(raw_bytes: &[u8]) -> Result { + match Self::identify_format(raw_bytes) { + CertFormat::Pem => Self::from_pem(raw_bytes), + CertFormat::Der => Self::from_der(raw_bytes), + } + } }