From 47a76fde77bac8eccb10fb8c7bdab3a512276199 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 --- src/certs/snp/cert.rs | 47 +++++++++++++++++++++++++++++++++++++++++++ src/error.rs | 18 +++++++++++++++++ 2 files changed, 65 insertions(+) diff --git a/src/certs/snp/cert.rs b/src/certs/snp/cert.rs index cde15420..c1a77237 100644 --- a/src/certs/snp/cert.rs +++ b/src/certs/snp/cert.rs @@ -2,6 +2,7 @@ use super::*; +use crate::error::CertFormatError; use openssl::pkey::{PKey, Public}; use openssl::x509::X509; @@ -10,6 +11,34 @@ use openssl::x509::X509; #[derive(Clone, Debug, Eq, PartialEq)] pub struct Certificate(X509); +#[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 +106,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), + } + } } diff --git a/src/error.rs b/src/error.rs index 86412d34..e2ce8c3f 100644 --- a/src/error.rs +++ b/src/error.rs @@ -11,6 +11,24 @@ use std::{ use std::os::raw::c_int; +#[cfg(feature = "openssl")] +#[derive(Clone, Copy, Debug, Eq, PartialEq)] +pub(crate) enum CertFormatError { + UnknownFormat, +} + +#[cfg(feature = "openssl")] +impl std::error::Error for CertFormatError {} + +#[cfg(feature = "openssl")] +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."), + } + } +} + /// An error representingthe upper 32 bits of a SW_EXITINFO2 field set by the VMM. #[derive(Debug, PartialEq, Eq, PartialOrd, Ord)] pub enum VmmError {