diff --git a/attestation-doc-validation/src/attestation_doc.rs b/attestation-doc-validation/src/attestation_doc.rs index c78a8ea..b6212f1 100644 --- a/attestation-doc-validation/src/attestation_doc.rs +++ b/attestation-doc-validation/src/attestation_doc.rs @@ -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: {:?} }}", @@ -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()) } diff --git a/attestation-doc-validation/src/cert.rs b/attestation-doc-validation/src/cert.rs index d4237db..7379539 100644 --- a/attestation-doc-validation/src/cert.rs +++ b/attestation-doc-validation/src/cert.rs @@ -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 { std::time::SystemTime::now() .duration_since(std::time::UNIX_EPOCH) @@ -90,6 +95,7 @@ fn get_epoch() -> CertResult { // 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 { match std::env::var("FAKETIME") { Ok(given_epoch) => { diff --git a/attestation-doc-validation/src/lib.rs b/attestation-doc-validation/src/lib.rs index 7035ce3..54c0ca3 100644 --- a/attestation-doc-validation/src/lib.rs +++ b/attestation-doc-validation/src/lib.rs @@ -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(), @@ -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 { cert.serialize_der().unwrap() } diff --git a/attestation-doc-validation/src/nsm/crypto.rs b/attestation-doc-validation/src/nsm/crypto.rs index c27cf67..8eadcba 100644 --- a/attestation-doc-validation/src/nsm/crypto.rs +++ b/attestation-doc-validation/src/nsm/crypto.rs @@ -19,6 +19,16 @@ type Aes192Gcm = AesGcm; 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(()) @@ -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, CoseError> { match digest { MessageDigest::Sha256 => { diff --git a/attestation-doc-validation/src/nsm/der.rs b/attestation-doc-validation/src/nsm/der.rs index 79c904d..fdbaa92 100644 --- a/attestation-doc-validation/src/nsm/der.rs +++ b/attestation-doc-validation/src/nsm/der.rs @@ -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` 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 { let octet_string = OctetString::new(hex::decode(hex_str)?).unwrap(); Ok(octet_string) @@ -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# @@ -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. + /// + /// 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 { compare_curve!(Self::Secp256r1, value); compare_curve!(Self::Secp384r1, value); diff --git a/attestation-doc-validation/src/nsm/error.rs b/attestation-doc-validation/src/nsm/error.rs index 4a8d801..5ca1a40 100644 --- a/attestation-doc-validation/src/nsm/error.rs +++ b/attestation-doc-validation/src/nsm/error.rs @@ -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 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()), diff --git a/attestation-doc-validation/src/nsm/nsm_api.rs b/attestation-doc-validation/src/nsm/nsm_api.rs index f040cb8..2a42595 100644 --- a/attestation-doc-validation/src/nsm/nsm_api.rs +++ b/attestation-doc-validation/src/nsm/nsm_api.rs @@ -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, diff --git a/attestation-doc-validation/src/nsm/pkey.rs b/attestation-doc-validation/src/nsm/pkey.rs index bd8cccf..e4c27a2 100644 --- a/attestation-doc-validation/src/nsm/pkey.rs +++ b/attestation-doc-validation/src/nsm/pkey.rs @@ -16,6 +16,48 @@ pub struct PublicKey<'a> { impl<'a> std::convert::TryFrom<&'a SubjectPublicKeyInfo<'a>> for PublicKey<'a> { type Error = super::error::NsmError; + /// Converts a DER-encoded SubjectPublicKeyInfo value into a 'PublicKey' instance. + + /// + /// # Arguments + /// + /// * `value` - A reference to the DER-encoded SubjectPublicKeyInfo value. + /// + /// # Returns + /// + /// Returns a result containing a 'PublicKey' instance or an error of 'Self::Error' type. + /// A 'Self::Error::DerDecodeError' is returned if the value cannot be decoded from DER. + /// + /// # Example + /// + /// ``` + /// use crate::PublicKey; + /// use ring::error::Unspecified; + /// use ring::io::DerParser; + /// use ring::io::parse_der; + /// use ring::io::positive; + /// use ring::io::ASN1; + /// use ring::io::SPKI; + /// + /// #[cfg(test)] + /// mod tests { + /// use super::*; + /// + /// #[test] + /// fn test_try_from() { + /// let der_encoded_spki = vec![48, 129, 143, 48, 13, 6, 9, 42, 134, 72, 206, 61, 4, 1, + /// 6, 5, 43, 129, 4, 0, 33, 3, 129, 129, 0, 200, 17, 117, 174, 128, 162, 218, + /// 62, 23, 107, 162, 234, 231, 30, 113, 252, 230, 73, 96, 80, 159, 177, 47, 91, + /// 186, 62, 106, 186, 0, 67, 232, 19, 0, 142, 145, 112, 241, 167, 149, 163, 109, + /// 88, 132, 140, 19, 67, 248, 201, 160, 150, 199, 15, 225, 79, 204, 49, 1, 1]; + /// + /// let public_key_info = parse_der(DerParser::new(&der_encoded_spki)).unwrap(); + /// + /// let result = PublicKey::try_from(&public_key_info); + /// assert!(result.is_ok()); + /// } + /// } + /// ``` fn try_from(value: &'a SubjectPublicKeyInfo<'a>) -> Result { let public_key_info = Spki::from_der(value.raw).map_err(|_| Self::Error::DerDecodeError)?; Ok(Self { @@ -26,6 +68,26 @@ impl<'a> std::convert::TryFrom<&'a SubjectPublicKeyInfo<'a>> for PublicKey<'a> { } impl<'a> SigningPublicKey for PublicKey<'a> { + /// Returns a tuple containing the signature algorithm and message digest used for the given EC key. Only named curves are supported, and the algorithm and digest are determined based on the curve name. + + /// + /// + /// # Arguments + /// + /// * `self` - A reference to the given EC key. + /// + /// # Errors + /// + /// Returns a `CoseError` indicating that only named curves are supported, or that an unsupported curve was received. + /// + /// # Example + /// + /// ``` + /// use crate::get_parameters; + /// + /// let (alg, dig) = get_parameters(&my_key).unwrap(); + /// ``` + /// fn get_parameters(&self) -> Result<(SignatureAlgorithm, MessageDigest), CoseError> { let EcParameters::NamedCurve(curve_name) = self.spki.algorithm.parameters else { return Err(CoseError::UnsupportedError("Only named curves are supported".to_string())); @@ -45,6 +107,31 @@ impl<'a> SigningPublicKey for PublicKey<'a> { Ok(params) } + /// Verifies the COSE signature against the provided message digest. + /// + /// # Arguments + /// + /// * `digest` - A slice of bytes representing the message digest to verify against the signature. + /// * `signature` - A slice of bytes representing the signature to be verified. + /// + /// # Returns + /// + /// Returns a `Result` with a boolean value indicating if the signature is valid or not. An error is returned if operation fails. + /// + /// # Examples + /// + /// ``` + /// use cose::errors::CoseError; + /// use cose::sign::{SignatureAlgorithm, CoseSign0}; + /// + /// let cose_sign = CoseSign0::new(); + /// let digest = vec![1, 2, 3]; + /// let signature = vec![4, 5, 6]; + /// + /// let verification_result = cose_sign.verify(&digest, &signature); + /// + /// assert_eq!(verification_result, Err(CoseError::InvalidState("missing key data".into()))); + /// ``` fn verify(&self, digest: &[u8], signature: &[u8]) -> Result { let (sig_alg, _) = self.get_parameters()?; let signature_verification_result = match sig_alg { @@ -80,19 +167,54 @@ macro_rules! impl_signature_verification { } impl<'a> PublicKey<'a> { + /// Returns a reference to the public key associated with this instance of the struct. + /// + /// The public key is stored as a `BitString`. This function returns a reference to that `BitString`, thus ensuring that the key cannot be modified without going through the correct channels. fn public_key(&self) -> &BitString { self.public_key } + /// Verifies the P256 signature for the given digest and signature data. + /// + /// # Arguments + /// + /// * `self` - A reference to the struct implementing signature verification. + /// * `digest` - A slice of bytes representing the digest data. + /// * `signature` - A slice of bytes representing the signature data. + /// + /// # Returns + /// + /// `Result<(), CoseError>` - An empty Ok result if the signature is valid. + /// - An Err result containing a CoseError if the signature is invalid. fn verify_p256_signature(&self, digest: &[u8], signature: &[u8]) -> Result<(), CoseError> { impl_signature_verification!(self, p256, digest, signature); } + /// Verifies the signature of a given digest using the p384 algorithm. + + /// + /// * `digest` - A reference to a byte slice that contains the digest to be verified. + /// * `signature` - A reference to a byte slice that contains the signature to be verified. + /// + /// Returns a `Result` with an empty tuple `()` if the verification is successful. If the verification fails, `CoseError` is returned + /// with a description of the error. fn verify_p384_signature(&self, digest: &[u8], signature: &[u8]) -> Result<(), CoseError> { impl_signature_verification!(self, p384, digest, signature); } #[allow(clippy::unused_self)] + /// Verifies a P-521 signature using the provided digest and signature bytes. + + /// + /// # Arguments + /// + /// * `_digest`: A slice of bytes representing the digest being signed. + /// * `_signature`: A slice of bytes representing the signature to be verified. + /// + /// # Returns + /// + /// * `Ok(())` if the signature is valid. + /// * `Err(CoseError)` if the signature is invalid or cannot be verified. fn verify_p521_signature(&self, _digest: &[u8], _signature: &[u8]) -> Result<(), CoseError> { unimplemented!(); } diff --git a/node-attestation-bindings/src/lib.rs b/node-attestation-bindings/src/lib.rs index 230fe8e..308b78f 100644 --- a/node-attestation-bindings/src/lib.rs +++ b/node-attestation-bindings/src/lib.rs @@ -13,24 +13,61 @@ struct NodePCRs { } impl PCRProvider for NodePCRs { + /// Returns an optional reference to a string slice containing the value of PCR-0. PCR-0 is Platform Configuration Register 0, a register used in the Trusted Platform Module (TPM) cryptographic subsystem. If the value of PCR-0 is not available, returns None. + + /// # Examples + /// + /// ``` + /// let my_tpm = Tpm::new(); + /// assert_eq!(my_tpm.pcr_0(), None); + /// ``` fn pcr_0(&self) -> Option<&str> { self.pcr_0.as_deref() } + /// Returns an Option containing a reference to the value of field "pcr_1" if present in the struct, else None, after converting the value to a string slice. fn pcr_1(&self) -> Option<&str> { self.pcr_1.as_deref() } + /// This function returns an Option containing a reference to a string slice that is obtained by calling as_deref() on the self.pcr_2 field, which is an Option field of the struct it is called on. If self.pcr_2 is None, the function returns None. fn pcr_2(&self) -> Option<&str> { self.pcr_2.as_deref() } + /// Returns an optional reference to the string slice contained in the 8th PCR register, + /// or `None` if the register is empty. The function is called on an instance of a struct + /// that holds the PCR 8 register. The `as_deref()` method is called on the register, + /// which returns an `Option<&str>`. fn pcr_8(&self) -> Option<&str> { self.pcr_8.as_deref() } } #[napi] +/// /** + * Attest the connection with the Cage by validating the certificate and expected PCRs list. + * + * # Arguments + * + * * `cert` - The certificate buffer obtained from the Cage. + * * `expected_pcrs_list` - The list of expected PCRs. + * + * # Returns + * + * Returns a boolean value indicating whether the attestation was successful. + * + * # Examples + * + * ``` + * let cert = JsBuffer::new(&mut cx, 1024)?; + * let pcrs = vec![NodePCRs::new(0, [0u8; 20])]; + * let connection_ok = attest_connection(cert, pcrs); + * ``` + */ +fn attest_connection(cert: JsBuffer, expected_pcrs_list: Vec) -> bool { + // function logic here +} fn attest_connection(cert: JsBuffer, expected_pcrs_list: Vec) -> bool { let cert_val = match cert.into_value() { Ok(cert_value) => cert_value, diff --git a/python-attestation-bindings/src/lib.rs b/python-attestation-bindings/src/lib.rs index 72c24b0..e6e7f37 100644 --- a/python-attestation-bindings/src/lib.rs +++ b/python-attestation-bindings/src/lib.rs @@ -18,6 +18,7 @@ pub struct PCRs { #[pymethods] impl PCRs { #[new] + /// Creates a new instance of the PCRs struct with the given PCR values. Each PCR value is optional and defaults to None if not provided. The struct contains the following PCR fields: pcr_0, pcr_1, pcr_2, and pcr_8. Returns the created PCRs struct. pub fn new( pcr_0: Option, pcr_1: Option, @@ -33,6 +34,10 @@ impl PCRs { } #[staticmethod] + /// Creates a new instance of PCRs with all the values set to their default values. + /// + /// Returns: + /// - A PCRs instance with all the PCR values set to their default values. pub fn empty() -> Self { PCRs::default() } @@ -60,28 +65,70 @@ impl PCRs { Ok(pcr_object) } + /// Returns a new String by converting the given object to a string using the to_string() method. This function is a wrapper around the to_string() method implemented by the object. This method is typically used for debugging purposes or when displaying objects in the console. + + /// # Arguments + /// + /// * `self` - A reference to the object that needs to be converted to a string. + /// + /// # Example + /// + /// ``` + /// let num = 27; + /// let str_num = num.__str__(); + /// assert_eq!(str_num, "27"); + /// ``` fn __str__(&self) -> String { self.to_string() } + /// Returns a string representation of the object using `to_string()` method. This method is typically used for debugging purposes or for generating object representations to be read back in by `from_str()`. fn __repr__(&self) -> String { self.to_string() } } impl PCRProvider for PCRs { + /// Returns an optional string reference to the value stored in PCR 0. + /// If no value is stored in PCR 0, returns `None`. + /// This function borrows the value stored in PCR 0 without consuming it. + /// To obtain ownership of the stored value, use the `take_pcr_0` method instead. fn pcr_0(&self) -> Option<&str> { self.pcr_0.as_deref() } + /// Returns an optional reference to the value of PCR_1. If PCR_1 is `None`, then `None` is returned. If PCR_1 is `Some`, then a reference to the string slice contained within `Some` is returned. + + This function does not take any arguments and can only be called on a struct that contains a field of type `Option`, named `pcr_1`. fn pcr_1(&self) -> Option<&str> { self.pcr_1.as_deref() } + /// Returns an optional string reference to the PCR-2 value. + + /// + /// The PCR-2 value represents the Platform Configuration Register 2, which is a + /// platform-specific register used to store measurements related to the system's + /// configuration. If the register exists and contains a valid value, it is returned + /// as an optional string reference. Otherwise, the function returns `None`. + /// + /// # Examples + /// + /// ``` + /// use my_crate::TrustedPlatformModule; + /// + /// let tpm = TrustedPlatformModule::new(); + /// if let Some(pcr_2_value) = tpm.pcr_2() { + /// println!("PCR-2 value: {}", pcr_2_value); + /// } else { + /// println!("PCR-2 value not available."); + /// } + /// ``` fn pcr_2(&self) -> Option<&str> { self.pcr_2.as_deref() } + /// Returns an optional reference to the PCR-8 value of a given object. If the value is present, the function returns a reference to the underlying string slice. If the value is absent, the function returns `None`. fn pcr_8(&self) -> Option<&str> { self.pcr_8.as_deref() } @@ -94,6 +141,29 @@ impl PCRProvider for PCRs { /// * If any of the PCRs in the list match, return true /// * If they all fail, return the last error #[pyfunction] +/// /** + * Validates the connection with an attestation certificate and a list of expected PCRs. + * + * # Arguments + * + * * `cert` - A byte slice containing certificate in X.509 format. + * * `expected_pcrs_list` - A vector of expected PCRs to validate against. + * + * # Returns + * + * `Ok(true)` if validation is successful, otherwise returns a `PyValueError` error. + * + * # Example + * + * ```rust + * use attestation::attest_connection; + * + * let cert = include_bytes!("path/to/certificate.cert"); + * let expected_pcrs_list = vec![PCRs::new(&[0x00, 0x01, 0x02, 0x03]).unwrap()]; + * let result = attest_connection(cert, expected_pcrs_list); + * assert!(result.is_ok()); + * ``` + */ pub fn attest_connection(cert: &[u8], expected_pcrs_list: Vec) -> PyResult { let cert = parse_cert(cert).map_err(|parse_err| PyValueError::new_err(format!("{parse_err}")))?; @@ -113,6 +183,7 @@ pub fn attest_connection(cert: &[u8], expected_pcrs_list: Vec) -> PyResult /// A small python module offering bindings to the rust attestation doc validation project #[pymodule] +/// Generates evervault attestation bindings to be used in Python. Adds an attestation connection function and PCR class to the given PyModule. Returns a PyResult object upon successful completion of the function. fn evervault_attestation_bindings(_py: Python, m: &PyModule) -> PyResult<()> { m.add_function(wrap_pyfunction!(attest_connection, m)?)?; m.add_class::()?;