use synta::{Integer, Null, OctetStringRef, RawDer};
use crate::builder::BuilderError;
use crate::cmp_types::{PKIBody, PKIHeader, PKIMessage};
use crate::GeneralNameSpec;
pub enum CMPBodySpec {
Pkiconf,
Ir(Vec<u8>),
Cr(Vec<u8>),
Kur(Vec<u8>),
P10cr(Vec<u8>),
Genm(Vec<u8>),
}
pub struct CMPMessageBuilder {
pvno: i64,
sender: Option<GeneralNameSpec>,
recipient: Option<GeneralNameSpec>,
transaction_id: Option<Vec<u8>>,
sender_nonce: Option<Vec<u8>>,
recip_nonce: Option<Vec<u8>>,
body: CMPBodySpec,
}
impl Default for CMPMessageBuilder {
fn default() -> Self {
Self::new()
}
}
impl CMPMessageBuilder {
pub fn new() -> Self {
Self {
pvno: 2,
sender: None,
recipient: None,
transaction_id: None,
sender_nonce: None,
recip_nonce: None,
body: CMPBodySpec::Pkiconf,
}
}
pub fn pvno(mut self, pvno: i64) -> Self {
self.pvno = pvno;
self
}
pub fn sender(mut self, gn: GeneralNameSpec) -> Self {
self.sender = Some(gn);
self
}
pub fn recipient(mut self, gn: GeneralNameSpec) -> Self {
self.recipient = Some(gn);
self
}
pub fn transaction_id(mut self, bytes: &[u8]) -> Self {
self.transaction_id = Some(bytes.to_vec());
self
}
pub fn sender_nonce(mut self, bytes: &[u8]) -> Self {
self.sender_nonce = Some(bytes.to_vec());
self
}
pub fn recip_nonce(mut self, bytes: &[u8]) -> Self {
self.recip_nonce = Some(bytes.to_vec());
self
}
pub fn body_pkiconf(mut self) -> Self {
self.body = CMPBodySpec::Pkiconf;
self
}
pub fn body_ir(mut self, cert_req_messages_der: &[u8]) -> Self {
self.body = CMPBodySpec::Ir(cert_req_messages_der.to_vec());
self
}
pub fn body_cr(mut self, cert_req_messages_der: &[u8]) -> Self {
self.body = CMPBodySpec::Cr(cert_req_messages_der.to_vec());
self
}
pub fn body_kur(mut self, cert_req_messages_der: &[u8]) -> Self {
self.body = CMPBodySpec::Kur(cert_req_messages_der.to_vec());
self
}
pub fn body_p10cr(mut self, csr_der: &[u8]) -> Self {
self.body = CMPBodySpec::P10cr(csr_der.to_vec());
self
}
pub fn body_genm(mut self, gen_msg_der: &[u8]) -> Self {
self.body = CMPBodySpec::Genm(gen_msg_der.to_vec());
self
}
pub fn build(self) -> Result<Vec<u8>, BuilderError> {
let sender_spec = self
.sender
.ok_or_else(|| BuilderError::EncodeError("sender is required".to_string()))?;
let recipient_spec = self
.recipient
.ok_or_else(|| BuilderError::EncodeError("recipient is required".to_string()))?;
let txid_bytes = self.transaction_id;
let snonce_bytes = self.sender_nonce;
let rnonce_bytes = self.recip_nonce;
let body_spec = self.body;
let sender = sender_spec
.to_general_name()
.map_err(|e| BuilderError::EncodeError(e.to_string()))?;
let recipient = recipient_spec
.to_general_name()
.map_err(|e| BuilderError::EncodeError(e.to_string()))?;
let transaction_id = txid_bytes.as_deref().map(OctetStringRef::new);
let sender_nonce = snonce_bytes.as_deref().map(OctetStringRef::new);
let recip_nonce = rnonce_bytes.as_deref().map(OctetStringRef::new);
let body = match body_spec {
CMPBodySpec::Pkiconf => PKIBody::Pkiconf(Null),
CMPBodySpec::Ir(ref bytes) => PKIBody::Ir(RawDer(bytes)),
CMPBodySpec::Cr(ref bytes) => PKIBody::Cr(RawDer(bytes)),
CMPBodySpec::Kur(ref bytes) => PKIBody::Kur(RawDer(bytes)),
CMPBodySpec::P10cr(ref bytes) => PKIBody::P10cr(RawDer(bytes)),
CMPBodySpec::Genm(ref bytes) => PKIBody::Genm(RawDer(bytes)),
};
let header = PKIHeader {
pvno: Integer::from_i64(self.pvno),
sender,
recipient,
message_time: None,
protection_alg: None,
sender_kid: None,
recip_kid: None,
transaction_id,
sender_nonce,
recip_nonce,
free_text: None,
general_info: None,
};
let msg = PKIMessage {
header,
body,
protection: None,
extra_certs: None,
};
msg.to_der()
.map_err(|e| BuilderError::EncodeError(e.to_string()))
}
}