Skip to content

Commit

Permalink
Switching to custom parser for binary.
Browse files Browse the repository at this point in the history
- Refactoring some misplaced code
- Adding custom parsing functionality
- Implemented new and updated existing unit tests to match new functionality
- Implemented parsing library in place of bincode where possible (eventually will completely remove it)
- Added clippy fixes
- Updated README.md

Signed-off-by: Larry Dewey <[email protected]>
  • Loading branch information
larrydewey committed Feb 25, 2025
1 parent 374d825 commit afd8d7a
Show file tree
Hide file tree
Showing 31 changed files with 2,056 additions and 931 deletions.
357 changes: 201 additions & 156 deletions Cargo.lock

Large diffs are not rendered by default.

7 changes: 4 additions & 3 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ iocuddle = "0.1"
openssl = { version = "0.10", optional = true }
serde = { version = "1.0", features = ["derive"] }
serde_bytes = "0.11"
serde_arrays = "0.1.0"
bitflags = "1.2"
codicon = "3.0"
dirs = "5.0"
Expand All @@ -69,12 +70,12 @@ x509-cert = { version = "0.2.5", optional = true }
byteorder = "1.4.3"
base64 = "0.22.1"
rdrand = { version = "^0.8", optional = true }
reqwest = { version="0.11.10", features = ["blocking"], optional = true }
tokio = {version = "1.29.1", features =["rt-multi-thread"], optional = true }
reqwest = { version = "0.11.10", features = ["blocking"], optional = true }
tokio = { version = "1.29.1", features = ["rt-multi-thread"], optional = true }

[target.'cfg(target_os = "linux")'.dev-dependencies]
kvm-ioctls = ">=0.16"
kvm-bindings = ">=0.9.1"

[dev-dependencies]
kvm-bindings = ">=0.9.1"
serial_test = "3.0"
2 changes: 1 addition & 1 deletion src/certs/sev/sev/cert/v1/body/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ use super::*;
#[repr(C, packed)]
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
pub struct Data {
pub firmware: crate::Version,
pub firmware: crate::firmware::host::Version,
pub reserved: u16,
pub key: key::PubKey,
}
Expand Down
7 changes: 3 additions & 4 deletions src/certs/sev/sev/cert/v1/sig/ecdsa.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,19 +6,18 @@ use {super::*, openssl::ecdsa};
use crate::util::hexdump;

use serde::{Deserialize, Serialize};
use serde_big_array::BigArray;

const SIG_PIECE_SIZE: usize = std::mem::size_of::<[u8; 72]>();

/// An ECDSA Signature.
#[repr(C)]
#[derive(Copy, Clone, Deserialize, Serialize)]
pub struct Signature {
#[serde(with = "BigArray")]
#[serde(with = "serde_arrays")]
r: [u8; 72],
#[serde(with = "BigArray")]
#[serde(with = "serde_arrays")]
s: [u8; 72],
#[serde(with = "BigArray")]
#[serde(with = "serde_arrays")]
_reserved: [u8; 512 - (SIG_PIECE_SIZE * 2)],
}

Expand Down
2 changes: 1 addition & 1 deletion src/certs/snp/builtin/mod.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
// SPDX-License-Identifier: Apache-2.0

/// Interfaces for retrieving builtin ARKs and ASKs for their respective generations.
//! Interfaces for retrieving builtin ARKs and ASKs for their respective generations.
/// Genoa generation.
pub mod genoa;
Expand Down
4 changes: 2 additions & 2 deletions src/certs/snp/ca/mod.rs
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
// SPDX-License-Identifier: Apache-2.0
//! Operations for a Certificate Authority (CA) chain.
#[cfg(feature = "openssl")]
use openssl::x509::X509;

use super::*;

/// Operations for a Certificate Authority (CA) chain.
/// A Certificate Authority (CA) chain.
#[derive(Clone, Debug)]
pub struct Chain {
Expand Down
82 changes: 56 additions & 26 deletions src/certs/snp/ecdsa/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
#[cfg(any(feature = "openssl", feature = "crypto_nossl"))]
use super::*;

use crate::util::hexdump;
use crate::{firmware::parser::ByteParser, util::hexdump};

#[cfg(feature = "openssl")]
use crate::certs::snp::{AsLeBytes, FromLe};
Expand All @@ -12,27 +12,34 @@ use crate::certs::snp::{AsLeBytes, FromLe};
use std::convert::TryFrom;

use serde::{Deserialize, Serialize};
use serde_big_array::BigArray;

#[cfg(feature = "openssl")]
use openssl::{bn, ecdsa};

const SIG_PIECE_SIZE: usize = std::mem::size_of::<[u8; 72]>();
const R_S_SIZE: usize = SIG_PIECE_SIZE * 2usize;
pub(crate) const SIG_PIECE_SIZE: usize = std::mem::size_of::<[u8; 72]>();
pub(crate) const R_S_SIZE: usize = SIG_PIECE_SIZE * 2usize;

#[repr(C)]
#[derive(Copy, Clone, Deserialize, Serialize, PartialOrd, Ord)]
/// ECDSA signature.
pub struct Signature {
#[serde(with = "BigArray")]
#[serde(with = "serde_arrays")]
r: [u8; 72],
#[serde(with = "BigArray")]
#[serde(with = "serde_arrays")]
s: [u8; 72],
#[serde(with = "BigArray")]
#[serde(with = "serde_arrays")]
_reserved: [u8; 512 - R_S_SIZE],
}

impl Signature {
/// Creates a new signature from the values specified
pub fn new(r: [u8; 72], s: [u8; 72]) -> Self {
Self {
r,
s,
..Default::default()
}
}
/// Returns the signatures `r` component
pub fn r(&self) -> &[u8; 72] {
&self.r
Expand All @@ -55,23 +62,46 @@ impl std::fmt::Debug for Signature {
}
}

impl Eq for Signature {}
impl PartialEq for Signature {
fn eq(&self, other: &Signature) -> bool {
self.r[..] == other.r[..] && self.s[..] == other.s[..]
impl Default for Signature {
fn default() -> Self {
ByteParser::default()
}
}

impl Default for Signature {
impl ByteParser for Signature {
type Bytes = [u8; 512];
#[inline(always)]
fn from_bytes(bytes: Self::Bytes) -> Self {
let mut r = [0; 72];
let mut s = [0; 72];
r.copy_from_slice(&bytes[0..72]);
s.copy_from_slice(&bytes[72..144]);
Self::new(r, s)
}
#[inline(always)]
fn to_bytes(&self) -> Self::Bytes {
let mut bytes = [0u8; 512];
bytes[0..72].copy_from_slice(&self.r);
bytes[72..144].copy_from_slice(&self.s);
bytes
}
#[inline(always)]
fn default() -> Self {
Signature {
r: [0u8; 72],
s: [0u8; 72],
_reserved: [0u8; (512 - (SIG_PIECE_SIZE * 2))],
Self {
r: [0; 72],
s: [0; 72],
_reserved: [0; 512 - R_S_SIZE],
}
}
}

impl Eq for Signature {}
impl PartialEq for Signature {
fn eq(&self, other: &Signature) -> bool {
self.r[..] == other.r[..] && self.s[..] == other.s[..]
}
}

impl std::fmt::Display for Signature {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(
Expand Down Expand Up @@ -159,7 +189,7 @@ mod tests {

#[test]
fn test_signature_default() {
let sig: Signature = Signature::default();
let sig: Signature = Default::default();
assert_eq!(sig.r(), &[0u8; 72]);
assert_eq!(sig.s(), &[0u8; 72]);
}
Expand All @@ -177,8 +207,8 @@ mod tests {

#[test]
fn test_signature_eq() {
let sig1: Signature = Signature::default();
let sig2: Signature = Signature::default();
let sig1: Signature = Default::default();
let sig2: Signature = Default::default();
let sig3: Signature = Signature {
r: [1u8; 72],
s: [0u8; 72],
Expand All @@ -191,7 +221,7 @@ mod tests {

#[test]
fn test_signature_ord() {
let sig1: Signature = Signature::default();
let sig1: Signature = Default::default();
let sig2: Signature = Signature {
r: [1u8; 72],
s: [0u8; 72],
Expand All @@ -203,15 +233,15 @@ mod tests {

#[test]
fn test_signature_debug() {
let sig: Signature = Signature::default();
let sig: Signature = Default::default();
let debug_str: String = format!("{:?}", sig);
assert!(debug_str.starts_with("Signature { r: "));
assert!(debug_str.contains(", s: "));
}

#[test]
fn test_signature_display() {
let sig: Signature = Signature::default();
let sig: Signature = Default::default();
let display_str: String = format!("{}", sig);
assert!(display_str.contains("Signature:"));
assert!(display_str.contains("R:"));
Expand Down Expand Up @@ -247,15 +277,15 @@ mod tests {

#[test]
fn test_try_into_ecdsa_sig() {
let sig = Signature::default();
let sig: Signature = Default::default();
let ecdsa_sig: ecdsa::EcdsaSig = (&sig).try_into().unwrap();
assert_eq!(ecdsa_sig.r().to_vec(), vec![]);
assert_eq!(ecdsa_sig.s().to_vec(), vec![]);
}

#[test]
fn test_try_into_vec() {
let sig = Signature::default();
let sig: Signature = Default::default();
let der: Vec<u8> = (&sig).try_into().unwrap();
assert!(!der.is_empty());
}
Expand All @@ -269,7 +299,7 @@ mod tests {
#[test]
#[should_panic]
fn test_try_into_p384_signature_failure() {
let signature: Signature = Signature::default();
let signature: Signature = Default::default();

let _p384_sig: p384::ecdsa::Signature = (&signature).try_into().unwrap();
}
Expand All @@ -290,7 +320,7 @@ mod tests {

#[test]
fn test_signature_serde() {
let sig: Signature = Signature::default();
let sig: Signature = Default::default();
let serialized: Vec<u8> = bincode::serialize(&sig).unwrap();
let deserialized: Signature = bincode::deserialize(&serialized).unwrap();
assert_eq!(sig, deserialized);
Expand Down
2 changes: 1 addition & 1 deletion src/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -117,7 +117,7 @@ impl Display for VmmError {

/// The raw firmware error.
#[derive(Debug)]
pub(crate) struct RawFwError(u64);
pub(crate) struct RawFwError(pub(crate) u64);

impl std::error::Error for RawFwError {}

Expand Down
31 changes: 27 additions & 4 deletions src/firmware/guest/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,6 @@ use crate::firmware::{
},
};

use std::convert::TryFrom;
#[cfg(target_os = "linux")]
use std::fs::{File, OpenOptions};

Expand All @@ -44,6 +43,7 @@ fn map_fw_err(raw_error: RawFwError) -> UserApiError {

/// A handle to the SEV-SNP guest device.
#[cfg(target_os = "linux")]
#[derive(Debug)]
pub struct Firmware(File);

#[cfg(target_os = "linux")]
Expand Down Expand Up @@ -110,7 +110,7 @@ impl Firmware {

let raw_report = response.report.as_array();

Ok(AttestationReport::try_from(raw_report.as_slice())?)
Ok(AttestationReport::from_bytes(&raw_report)?)
}

/// Request an extended attestation report from the AMD Secure Processor.
Expand Down Expand Up @@ -182,9 +182,9 @@ impl Firmware {
Err(FirmwareError::from(report_response.status))?
}

let raw_report = report_response.report.as_array();
let raw_report = report_response.report;

let report = AttestationReport::try_from(raw_report.as_slice())?;
let report = AttestationReport::from_bytes(&raw_report)?;

if ext_report_request.certs_len == 0 {
return Ok((report, None));
Expand Down Expand Up @@ -241,3 +241,26 @@ impl Firmware {
Ok(ffi_derived_key_response.key)
}
}

#[cfg(test)]
mod tests {
use super::*;

#[test]
fn test_firmware_error_mapping() {
let raw_error = RawFwError(1); // Lower byte error
let error = map_fw_err(raw_error);
assert!(matches!(error, UserApiError::FirmwareError(_)));

let raw_error = RawFwError(0x100000000u64); // Upper byte error
let error = map_fw_err(raw_error);
assert!(matches!(error, UserApiError::VmmError(_)));

let raw_error = RawFwError(0x0u64); // lower byte error
let error = map_fw_err(raw_error);
assert!(matches!(
error,
UserApiError::FirmwareError(FirmwareError::UnknownSevError(0))
));
}
}
Loading

0 comments on commit afd8d7a

Please sign in to comment.