use crate::cert::gen::{CertGenerator, CertType, IssuerDN, SubjectDN, Validity};
use crate::cert::CertRef;
use crate::crypto::{
CanonPkcPublicKey, CanonPkcSecretKey, CanonPkcSecretKeyRef, Crypto, PublicKey, RngCore,
SecretKey, SigningSecretKey,
};
use crate::error::Error;
use crate::tlv::TLVElement;
pub struct RcacGenerator<'a> {
buf: &'a mut [u8],
}
impl<'a> RcacGenerator<'a> {
pub const fn new(buf: &'a mut [u8]) -> Self {
Self { buf }
}
pub fn generate<C: Crypto>(
&mut self,
crypto: C,
fabric_id: u64,
validity: Validity,
) -> Result<(CanonPkcSecretKey, &[u8]), Error> {
let mut rcac_id_bytes = [0u8; 8];
crypto.rand()?.fill_bytes(&mut rcac_id_bytes);
let rcac_id = u64::from_be_bytes(rcac_id_bytes);
let rcac_key = crypto.generate_secret_key()?;
let mut rcac_pubkey_canon = CanonPkcPublicKey::new();
rcac_key.pub_key()?.write_canon(&mut rcac_pubkey_canon)?;
let mut serial_bytes = [0u8; 8];
crypto.rand()?.fill_bytes(&mut serial_bytes);
let cert_len = CertGenerator::new(self.buf).generate(
&crypto,
CertType::Rcac,
&serial_bytes,
validity,
SubjectDN {
node_id: None,
fabric_id: Some(fabric_id),
cat_ids: &[],
ca_id: Some(rcac_id),
},
IssuerDN {
ca_id: None,
fabric_id: None,
is_rcac: false,
},
rcac_pubkey_canon.reference(),
None, &rcac_key,
)?;
let mut rcac_privkey = CanonPkcSecretKey::new();
rcac_key.write_canon(&mut rcac_privkey)?;
Ok((rcac_privkey, &self.buf[..cert_len]))
}
}
pub struct IcacGenerator<'a> {
buf: &'a mut [u8],
}
impl<'a> IcacGenerator<'a> {
pub const fn new(buf: &'a mut [u8]) -> Self {
Self { buf }
}
pub fn generate<C: Crypto>(
&mut self,
crypto: C,
rcac_privkey: CanonPkcSecretKeyRef<'_>,
rcac_bytes: &[u8],
validity: Validity,
) -> Result<(CanonPkcSecretKey, &[u8]), Error> {
let rcac = CertRef::new(TLVElement::new(rcac_bytes));
let rcac_pubkey = rcac.pubkey()?.try_into()?;
let rcac_id = rcac.get_ca_id()?;
let fabric_id = rcac.get_fabric_id()?;
let mut icac_id_bytes = [0u8; 8];
crypto.rand()?.fill_bytes(&mut icac_id_bytes);
let icac_id = u64::from_be_bytes(icac_id_bytes);
let icac_key = crypto.generate_secret_key()?;
let mut icac_pubkey_canon = CanonPkcPublicKey::new();
icac_key.pub_key()?.write_canon(&mut icac_pubkey_canon)?;
let rcac_signing_key = crypto.secret_key(rcac_privkey)?;
let mut serial_bytes = [0u8; 8];
crypto.rand()?.fill_bytes(&mut serial_bytes);
let cert_len = CertGenerator::new(self.buf).generate(
&crypto,
CertType::Icac,
&serial_bytes,
validity,
SubjectDN {
node_id: None,
fabric_id: Some(fabric_id),
cat_ids: &[],
ca_id: Some(icac_id),
},
IssuerDN {
ca_id: Some(rcac_id),
fabric_id: Some(fabric_id),
is_rcac: true,
},
icac_pubkey_canon.reference(),
Some(rcac_pubkey),
&rcac_signing_key,
)?;
let mut icac_privkey = CanonPkcSecretKey::new();
icac_key.write_canon(&mut icac_privkey)?;
Ok((icac_privkey, &self.buf[..cert_len]))
}
}
#[cfg(test)]
mod tests {
use crate::cert::gen::VALID_FOREVER;
use crate::cert::{CertRef, MAX_CERT_TLV_AND_ASN1_LEN};
use crate::crypto::test_only_crypto;
use crate::tlv::TLVElement;
use super::*;
#[test]
fn rcac_carries_supplied_fabric_id() {
let crypto = test_only_crypto();
let mut cert_buf = [0; MAX_CERT_TLV_AND_ASN1_LEN];
let mut rcac_gen = RcacGenerator::new(&mut cert_buf);
let (_priv, rcac) = rcac_gen
.generate(&crypto, 0xABCD1234, VALID_FOREVER)
.unwrap();
let cert = CertRef::new(TLVElement::new(rcac));
assert_eq!(cert.get_fabric_id().unwrap(), 0xABCD1234);
let _ = cert.get_ca_id().unwrap();
}
#[test]
fn icac_inherits_rcac_fabric_id() {
let crypto = test_only_crypto();
let fabric_id = 0x0102030405060708u64;
let mut cert_buf1 = [0; MAX_CERT_TLV_AND_ASN1_LEN];
let mut rcac_gen = RcacGenerator::new(&mut cert_buf1);
let (rcac_priv, rcac) = rcac_gen
.generate(&crypto, fabric_id, VALID_FOREVER)
.unwrap();
let mut cert_buf2 = [0; MAX_CERT_TLV_AND_ASN1_LEN];
let mut icac_gen = IcacGenerator::new(&mut cert_buf2);
let (_icac_priv, icac) = icac_gen
.generate(&crypto, rcac_priv.reference(), rcac, VALID_FOREVER)
.unwrap();
let icac_cert = CertRef::new(TLVElement::new(icac));
assert_eq!(icac_cert.get_fabric_id().unwrap(), fabric_id);
let _ = icac_cert.get_ca_id().unwrap();
}
}