#![forbid(unsafe_code)]
use thiserror::Error;
#[derive(Debug, Error)]
#[non_exhaustive]
pub enum NocError {
#[error("NOCSR TLV parse failure")]
NocsrParse(#[source] Box<dyn std::error::Error + Send + Sync + 'static>),
#[error("embedded PKCS#10 CSR parse failure")]
CsrParse(#[source] Box<dyn std::error::Error + Send + Sync + 'static>),
#[error("CSR self-signature verification failed")]
BadCsrSelfSignature,
#[error("CSRNonce did not match commissioner-issued value")]
NonceMismatch,
#[error("DAC attestation signature over NOCSR failed")]
BadCsrAttestationSignature,
#[error("CSR public key is not a valid P-256 point")]
InvalidCsrPublicKey,
#[error("Matter DN attribute construction failed")]
DnAttributeOverflow,
#[error("NOC certificate construction failed")]
CertBuild(#[source] matter_cert::Error),
#[error("NOC signing failed")]
SigningFailed(#[source] matter_crypto::SignerError),
#[error("RNG failure")]
Rng,
#[error("OpCreds cluster payload codec error")]
ClusterCodec(#[source] matter_codec::Error),
#[error("OpCreds cluster response is structurally malformed: {0}")]
MalformedResponse(&'static str),
}
impl From<matter_codec::Error> for NocError {
fn from(e: matter_codec::Error) -> Self {
Self::ClusterCodec(e)
}
}
pub trait NocRng: Send + Sync + std::fmt::Debug {
fn fill(&self, dest: &mut [u8]) -> Result<(), NocError>;
}
#[derive(Debug, Default)]
pub struct SystemNocRng;
impl NocRng for SystemNocRng {
fn fill(&self, dest: &mut [u8]) -> Result<(), NocError> {
use ring::rand::SecureRandom;
ring::rand::SystemRandom::new()
.fill(dest)
.map_err(|_| NocError::Rng)
}
}
#[cfg(test)]
#[allow(clippy::unwrap_used)] mod tests {
use super::*;
#[test]
fn system_rng_fills_distinct_bytes() {
let mut a = [0u8; 32];
let mut b = [0u8; 32];
SystemNocRng.fill(&mut a).unwrap();
SystemNocRng.fill(&mut b).unwrap();
assert_ne!(a, b, "two random draws collided — RNG is not wired");
assert_ne!(a, [0u8; 32], "RNG returned all zeros");
}
}