use crate::{builder::Error, OcspRequest, Request, Signature, TbsRequest, Version};
use alloc::vec::Vec;
use der::Encode;
use rand_core::CryptoRngCore;
use signature::{RandomizedSigner, Signer};
use spki::{DynSignatureAlgorithmIdentifier, SignatureBitStringEncoding};
use x509_cert::{
ext::{pkix::name::GeneralName, AsExtension},
name::Name,
Certificate,
};
#[derive(Clone, Debug, Default)]
pub struct OcspRequestBuilder {
tbs: TbsRequest,
}
impl OcspRequestBuilder {
pub fn new(version: Version) -> Self {
Self {
tbs: TbsRequest {
version,
requestor_name: None,
request_list: Vec::new(),
request_extensions: None,
},
}
}
pub fn with_requestor_name(mut self, requestor_name: GeneralName) -> Self {
self.tbs.requestor_name = Some(requestor_name);
self
}
pub fn with_request(mut self, request: Request) -> Self {
self.tbs.request_list.push(request);
self
}
pub fn with_extension(mut self, ext: impl AsExtension) -> Result<Self, Error> {
let ext = ext.to_extension(&Name::default(), &[])?;
match self.tbs.request_extensions {
Some(ref mut exts) => exts.push(ext),
None => self.tbs.request_extensions = Some(alloc::vec![ext]),
}
Ok(self)
}
pub fn build(self) -> OcspRequest {
OcspRequest {
tbs_request: self.tbs,
optional_signature: None,
}
}
pub fn sign<S, Sig>(
self,
signer: &mut S,
certificate_chain: Option<Vec<Certificate>>,
) -> Result<OcspRequest, Error>
where
S: Signer<Sig> + DynSignatureAlgorithmIdentifier,
Sig: SignatureBitStringEncoding,
{
let signature_algorithm = signer.signature_algorithm_identifier()?;
let signature = signer.try_sign(&self.tbs.to_der()?)?.to_bitstring()?;
let optional_signature = Some(Signature {
signature_algorithm,
signature,
certs: certificate_chain,
});
Ok(OcspRequest {
tbs_request: self.tbs,
optional_signature,
})
}
pub fn sign_with_rng<S, Sig>(
self,
signer: &mut S,
rng: &mut impl CryptoRngCore,
certificate_chain: Option<Vec<Certificate>>,
) -> Result<OcspRequest, Error>
where
S: RandomizedSigner<Sig> + DynSignatureAlgorithmIdentifier,
Sig: SignatureBitStringEncoding,
{
let signature_algorithm = signer.signature_algorithm_identifier()?;
let signature = signer
.try_sign_with_rng(rng, &self.tbs.to_der()?)?
.to_bitstring()?;
let optional_signature = Some(Signature {
signature_algorithm,
signature,
certs: certificate_chain,
});
Ok(OcspRequest {
tbs_request: self.tbs,
optional_signature,
})
}
}