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

add doc comments #53

Draft
wants to merge 1 commit into
base: main
Choose a base branch
from
Draft
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
37 changes: 37 additions & 0 deletions attestation-doc-validation/src/attestation_doc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,26 @@ pub trait PCRProvider {
fn pcr_2(&self) -> Option<&str>;
fn pcr_8(&self) -> Option<&str>;

/// Returns a string representation of the PCRS struct.
///
/// The returned string includes the values of PCR0, PCR1, PCR2 and PCR8
/// in a formatted string.
///
/// # Arguments
///
/// * `self` - A reference to the PCRS struct
///
/// # Example
///
/// ```rust
/// use my_crate::PCRS;
///
/// let pcrs = PCRS::new();
///
/// let pcrs_str = pcrs.to_string();
///
/// println!("{}", pcrs_str); // prints "PCRS { PCR0: ..., PCR1: ..., PCR2: ..., PCR8: ... }"
/// ```
fn to_string(&self) -> String {
format!(
"PCRS {{ PCR0: {:?}, PCR1: {:?}, PCR2: {:?}, PCR8: {:?} }}",
Expand Down Expand Up @@ -67,15 +87,32 @@ pub struct PCRs {
}

impl PCRProvider for PCRs {
/// Returns an optional reference to a string slice representing the value of PCR_0. If the value of PCR_0 is present, it will be returned as `Some(&str)`. If it is absent, `None` will be returned. This method is immutable and does not modify the current state of the struct.
fn pcr_0(&self) -> Option<&str> {
Some(self.pcr_0.as_str())
}
/// Returns an optional reference to a string slice that represents the value of PCR 1. If the value of PCR 1 is present, it is returned as a Some. If the value of PCR 1 is absent, it is returned as a None.
fn pcr_1(&self) -> Option<&str> {
Some(self.pcr_1.as_str())
}
/// Returns an optional reference to the second Platform Configuration Register (PCR 2).
///
/// If the reference to the string is present, it contains the value of the PCR 2.
/// If it is not present, it means that the PCR 2 has not been set or has been deleted.
/// This function allows for safe access to the PCR 2 value without risking modifying the original
/// value.
fn pcr_2(&self) -> Option<&str> {
Some(self.pcr_2.as_str())
}
/// Returns an optional reference to a string slice containing the PCR-8 value. If the value is present, it is returned as a `Some(&str)`. If the value is missing, this function returns `None`.
///
/// # Arguments
///
/// - `&self`: A reference to a `Self` struct instance.
///
/// # Returns
///
/// An optional immutable reference to a string slice representing the PCR-8 value.
fn pcr_8(&self) -> Option<&str> {
Some(self.pcr_8.as_str())
}
Expand Down
6 changes: 6 additions & 0 deletions attestation-doc-validation/src/cert.rs
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,11 @@ pub(super) fn export_public_key_to_der<'a>(cert: &'a X509Certificate) -> &'a [u8
///
/// Returns a `CertError::TimeError` when the current timestamp is before the unix epoch...
#[cfg(not(test))]
/// /// This function returns the number of seconds since the UNIX Epoch (January 1, 1970).
/// It uses the `SystemTime` trait from the `std::time` module to get the current time.
/// The `duration_since` method is called on this time to calculate the duration since the UNIX Epoch.
/// Finally, the `as_secs` method is called to get the number of seconds since the UNIX Epoch.
/// If an error occurs during the process, a `CertError` with the `TimeError` variant is returned.
fn get_epoch() -> CertResult<u64> {
std::time::SystemTime::now()
.duration_since(std::time::UNIX_EPOCH)
Expand All @@ -90,6 +95,7 @@ fn get_epoch() -> CertResult<u64> {

// Testing version of this function attempts to get the timestamp to use from env vars
#[cfg(test)]
/// This function returns the current epoch in seconds since Unix epoch (January 1, 1970, 00:00:00 UTC). If the FAKETIME environment variable is set, it returns the epoch specified in the variable. If the variable is invalid or not set, it returns the current epoch. If an error occurs during the calculation, it returns an error of type CertError::TimeError.
fn get_epoch() -> CertResult<u64> {
match std::env::var("FAKETIME") {
Ok(given_epoch) => {
Expand Down
36 changes: 36 additions & 0 deletions attestation-doc-validation/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,23 @@ mod test {

use rcgen::generate_simple_self_signed;

/// Embeds attestation document in the certificate for the provided hostname and cose bytes.
///
/// # Arguments
/// * `hostname`: A string slice representing the hostname for which the certificate is being generated.
/// * `cose_bytes`: A slice of `u8` representing the cose bytes to be embedded in the certificate.
///
/// # Returns
/// A newly generated `rcgen::Certificate` containing the attestation document embedded within the provided hostname.
///
/// # Example
/// ```
/// use rcgen::Certificate;
///
/// let hostname = "example.com";
/// let cose_bytes: [u8; 4] = [0x1, 0x2, 0x3, 0x4];
/// let cert = embed_attestation_doc_in_cert(hostname, &cose_bytes);
/// ```
fn embed_attestation_doc_in_cert(hostname: &str, cose_bytes: &[u8]) -> rcgen::Certificate {
let subject_alt_names = vec![
hostname.to_string(),
Expand All @@ -124,6 +141,25 @@ mod test {
generate_simple_self_signed(subject_alt_names).unwrap()
}

/// Converts an RCgen certificate to DER encoding and returns the resulting byte vector.

///
/// # Arguments
///
/// * `cert` - An RCgen certificate to be serialized to DER format.
///
/// # Returns
///
/// The byte vector representing the serialized certificate in DER format.
///
/// # Examples
///
/// ```
/// use rcgen::generate_simple_self_signed;
///
/// let cert = generate_simple_self_signed(vec!["localhost".into()]).unwrap();
/// let der_cert = rcgen_cert_to_der(cert);
/// ```
fn rcgen_cert_to_der(cert: rcgen::Certificate) -> Vec<u8> {
cert.serialize_der().unwrap()
}
Expand Down
37 changes: 37 additions & 0 deletions attestation-doc-validation/src/nsm/crypto.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,16 @@ type Aes192Gcm = AesGcm<Aes192, U12>;
pub(crate) struct CryptoClient;

impl Entropy for CryptoClient {
/// Generates cryptographically secure random bytes and stores them in the provided buffer.

///
/// # Arguments
///
/// * `buff` - A mutable reference to an array of u8 bytes to be filled with random bytes
///
/// # Returns
///
/// * `Result<(), CoseError>` - `Ok(())` if execution was successful, otherwise a `CoseError` is returned.
fn rand_bytes(buff: &mut [u8]) -> Result<(), CoseError> {
OsRng.fill_bytes(buff);
Ok(())
Expand Down Expand Up @@ -134,6 +144,33 @@ macro_rules! compute_hash {
}

impl Hash for CryptoClient {
/// /**
* Computes the hash of the input data using the specified digest
* algorithm.
*
* # Arguments
*
* * `digest` - The digest algorithm to use (must be one of Sha256,
* Sha384, or Sha512)
* * `data` - The data to hash
*
* # Returns
*
* The resulting hash as a byte vector or an error of type `CoseError`.
*
* # Example
*
* ```
* use openssl::hash::MessageDigest;
* use cose::util::hash;
*
* let data = &[0xF1, 0xF2, 0xF3, 0xF4, 0xF5];
* let digest = MessageDigest::Sha256;
*
* let result = hash(digest, data);
* assert!(result.is_ok());
* ```
*/
fn hash(digest: MessageDigest, data: &[u8]) -> Result<Vec<u8>, CoseError> {
match digest {
MessageDigest::Sha256 => {
Expand Down
33 changes: 33 additions & 0 deletions attestation-doc-validation/src/nsm/der.rs
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,26 @@ pub struct SubjectPublicKeyInfo<'a> {
pub subject_public_key: BitString,
}

/// Converts a hexadecimal string into an OctetString.
///
/// # Arguments
///
/// * `hex_str` - a string slice that contains the hexadecimal representation of the octet string.
///
/// # Returns
///
/// * A `Result<OctetString, hex::FromHexError>` where the success variant contains the OctetString decoded from the hexadecimal string,
/// and the error variant indicates that the string could not be parsed as hexadecimal.
///
/// # Examples
///
/// ```
/// use my_crate::OctetString;
///
/// let hex_str = "68656c6c6f20776f726c64"; // "hello world" in hex
/// let octet_string = OctetString::from_hex(hex_str).unwrap();
/// assert_eq!(octet_string.to_string(), "hello world");
/// ```
pub fn octet_string_from_hex(hex_str: &str) -> Result<OctetString, hex::FromHexError> {
let octet_string = OctetString::new(hex::decode(hex_str)?).unwrap();
Ok(octet_string)
Expand All @@ -56,6 +76,7 @@ pub enum SupportedEcCurve {
}

impl SupportedEcCurve {
/// Returns a `Curve` object based on the selected elliptic curve. The available options are `Secp256r1`, `Secp384r1`, and `Secp521r1`, each with their respective parameters sourced from official standards. The `Curve` object contains the `a` and `b` parameters of the curve, as well as a `BitString` seed value.
fn to_curve(&self) -> Curve {
match self {
// Parameters from: https://neuromancer.sk/std/secg/secp256r1#
Expand Down Expand Up @@ -106,6 +127,18 @@ macro_rules! compare_curve {

impl std::convert::TryFrom<&Curve> for SupportedEcCurve {
type Error = ();
/// Attempts to convert the given reference to a Curve into Self, the concrete type implementing TryFrom<Curve>.
///
/// If the given reference to a Curve is not one of the supported curves - Secp256r1, Secp384r1 or Secp521r1 - the function will return an error.
///
/// # Arguments
///
/// * `value` - A reference to a Curve that needs to be converted to Self.
///
/// # Returns
///
/// * `Ok(Self)` - If `value` is successfully converted to Self.
/// * `Err(())` - If `value` is not one of the supported curves.
fn try_from(value: &Curve) -> Result<Self, Self::Error> {
compare_curve!(Self::Secp256r1, value);
compare_curve!(Self::Secp384r1, value);
Expand Down
19 changes: 19 additions & 0 deletions attestation-doc-validation/src/nsm/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,25 @@ where
// Impl to support casting errors from AWS types to ours
use aws_nitro_enclaves_cose::error::CoseError;
impl std::convert::From<CoseError> for NsmError {
/// Converts a `CoseError` into an `NsmError`.
///
/// # Arguments
///
/// * `value` - A `CoseError` that needs to be converted into an `NsmError`.
///
/// # Returns
///
/// An `NsmError` that corresponds to the input `CoseError`.
///
/// # Example
///
/// ```
/// use my_crate::{CoseError, NsmError, from};
///
/// let cose_err = CoseError::EntropyError("Failed to generate entropy".to_string());
/// let nsm_err = from(cose_err);
/// assert_eq!(nsm_err, NsmError::EntropyError("Failed to generate entropy".to_string()));
/// ```
fn from(value: CoseError) -> NsmError {
match value {
CoseError::EntropyError(inner) => NsmError::EntropyError(inner.to_string()),
Expand Down
13 changes: 13 additions & 0 deletions attestation-doc-validation/src/nsm/nsm_api.rs
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,19 @@ impl AttestationDoc {
/// * nonce: optional cryptographic nonce that will be included in the `AttestationDoc`
/// * `public_key`: optional DER-encoded public key that will be included in the `AttestationDoc`
#[allow(clippy::too_many_arguments)]
/// Creates a new AttestationDoc struct with the given parameters.
///
/// # Arguments
///
/// * `module_id` - A String representing the ID of the module.
/// * `digest` - A Digest representing the hash of the module.
/// * `timestamp` - An unsigned 64-bit integer representing the timestamp of the attestation.
/// * `pcrs` - A BTreeMap of unsigned integers to byte vectors representing the values of the platform configuration registers.
/// * `certificate` - A byte vector representing the certificate used for the attestation.
/// * `cabundle` - A vector of byte vectors representing the chain of trust for the certificate.
/// * `user_data` - An optional byte vector representing user data to include in the attestation.
/// * `nonce` - An optional byte vector representing a nonce to include in the attestation.
/// * `public_key` - An optional byte vector representing the public key used for the attestation.
pub fn new(
module_id: String,
digest: Digest,
Expand Down
Loading