use async_trait::async_trait;
use crate::{
crypto::{
raw_signature::{AsyncRawSigner, RawSigner, RawSignerError, SigningAlg},
time_stamp::{TimeStampError, TimeStampProvider},
},
dynamic_assertion::{AsyncDynamicAssertion, DynamicAssertion},
http::SyncGenericResolver,
maybe_send_sync::{MaybeSend, MaybeSync},
Result,
};
#[cfg(not(target_arch = "wasm32"))]
pub type BoxedSigner = Box<dyn Signer + Send + Sync>;
#[cfg(target_arch = "wasm32")]
pub type BoxedSigner = Box<dyn Signer>;
#[cfg(not(target_arch = "wasm32"))]
pub type BoxedAsyncSigner = Box<dyn AsyncSigner + Send + Sync>;
#[cfg(target_arch = "wasm32")]
pub type BoxedAsyncSigner = Box<dyn AsyncSigner>;
pub trait Signer {
fn sign(&self, data: &[u8]) -> Result<Vec<u8>>;
fn alg(&self) -> SigningAlg;
fn certs(&self) -> Result<Vec<Vec<u8>>>;
fn reserve_size(&self) -> usize;
fn time_authority_url(&self) -> Option<String> {
None
}
fn timestamp_request_headers(&self) -> Option<Vec<(String, String)>> {
None
}
fn timestamp_request_body(&self, message: &[u8]) -> Result<Vec<u8>> {
crate::crypto::time_stamp::default_rfc3161_message(message).map_err(|e| e.into())
}
fn send_timestamp_request(&self, message: &[u8]) -> Option<Result<Vec<u8>>> {
if let Some(url) = self.time_authority_url() {
if let Ok(body) = self.timestamp_request_body(message) {
let headers: Option<Vec<(String, String)>> = self.timestamp_request_headers();
return Some(
crate::crypto::time_stamp::default_rfc3161_request(
&url,
headers,
&body,
message,
&SyncGenericResolver::with_redirects().unwrap_or_default(),
)
.map_err(|e| e.into()),
);
}
}
None
}
fn ocsp_val(&self) -> Option<Vec<u8>> {
None
}
fn direct_cose_handling(&self) -> bool {
false
}
fn dynamic_assertions(&self) -> Vec<Box<dyn DynamicAssertion>> {
Vec::new()
}
fn raw_signer(&self) -> Option<Box<&dyn RawSigner>> {
None
}
}
#[allow(dead_code)] pub(crate) trait ConfigurableSigner: Signer + Sized {
#[cfg(feature = "file_io")]
fn from_files<P: AsRef<std::path::Path>>(
signcert_path: P,
pkey_path: P,
alg: SigningAlg,
tsa_url: Option<String>,
) -> Result<Self> {
let signcert = std::fs::read(signcert_path).map_err(crate::Error::IoError)?;
let pkey = std::fs::read(pkey_path).map_err(crate::Error::IoError)?;
Self::from_signcert_and_pkey(&signcert, &pkey, alg, tsa_url)
}
fn from_signcert_and_pkey(
signcert: &[u8],
pkey: &[u8],
alg: SigningAlg,
tsa_url: Option<String>,
) -> Result<Self>;
}
#[cfg_attr(not(target_arch = "wasm32"), async_trait)]
#[cfg_attr(target_arch = "wasm32", async_trait(?Send))]
pub trait AsyncSigner: MaybeSend + MaybeSync {
async fn sign(&self, data: Vec<u8>) -> Result<Vec<u8>>;
fn alg(&self) -> SigningAlg;
fn certs(&self) -> Result<Vec<Vec<u8>>>;
fn reserve_size(&self) -> usize;
fn time_authority_url(&self) -> Option<String> {
None
}
fn timestamp_request_headers(&self) -> Option<Vec<(String, String)>> {
None
}
fn timestamp_request_body(&self, message: &[u8]) -> Result<Vec<u8>> {
crate::crypto::time_stamp::default_rfc3161_message(message).map_err(|e| e.into())
}
async fn send_timestamp_request(&self, message: &[u8]) -> Option<Result<Vec<u8>>> {
if let Some(url) = self.time_authority_url() {
if let Ok(body) = self.timestamp_request_body(message) {
use crate::http::AsyncGenericResolver;
let headers: Option<Vec<(String, String)>> = self.timestamp_request_headers();
return Some(
crate::crypto::time_stamp::default_rfc3161_request_async(
&url,
headers,
&body,
message,
&AsyncGenericResolver::with_redirects().unwrap_or_default(),
)
.await
.map_err(|e| e.into()),
);
}
}
None
}
async fn ocsp_val(&self) -> Option<Vec<u8>> {
None
}
fn direct_cose_handling(&self) -> bool {
false
}
fn dynamic_assertions(&self) -> Vec<Box<dyn AsyncDynamicAssertion>> {
Vec::new()
}
fn async_raw_signer(&self) -> Option<Box<&dyn AsyncRawSigner>> {
None
}
}
impl<T: ?Sized + Signer> Signer for Box<T> {
fn sign(&self, data: &[u8]) -> Result<Vec<u8>> {
(**self).sign(data)
}
fn alg(&self) -> SigningAlg {
(**self).alg()
}
fn certs(&self) -> Result<Vec<Vec<u8>>> {
(**self).certs()
}
fn reserve_size(&self) -> usize {
(**self).reserve_size()
}
fn ocsp_val(&self) -> Option<Vec<u8>> {
(**self).ocsp_val()
}
fn direct_cose_handling(&self) -> bool {
(**self).direct_cose_handling()
}
fn dynamic_assertions(&self) -> Vec<Box<dyn DynamicAssertion>> {
(**self).dynamic_assertions()
}
fn time_authority_url(&self) -> Option<String> {
(**self).time_authority_url()
}
fn timestamp_request_headers(&self) -> Option<Vec<(String, String)>> {
(**self).timestamp_request_headers()
}
fn timestamp_request_body(&self, message: &[u8]) -> Result<Vec<u8>> {
(**self).timestamp_request_body(message)
}
fn send_timestamp_request(&self, message: &[u8]) -> Option<Result<Vec<u8>>> {
(**self).send_timestamp_request(message)
}
fn raw_signer(&self) -> Option<Box<&dyn RawSigner>> {
(**self).raw_signer()
}
}
impl RawSigner for Box<dyn Signer> {
fn sign(&self, data: &[u8]) -> std::result::Result<Vec<u8>, RawSignerError> {
Ok(self.as_ref().sign(data)?)
}
fn alg(&self) -> SigningAlg {
self.as_ref().alg()
}
fn cert_chain(&self) -> std::result::Result<Vec<Vec<u8>>, RawSignerError> {
Ok(self.as_ref().certs()?)
}
fn reserve_size(&self) -> usize {
self.as_ref().reserve_size()
}
fn ocsp_response(&self) -> Option<Vec<u8>> {
eprintln!("HUH, A DIFFERENT I WANTED @ 397");
self.as_ref().ocsp_val()
}
}
impl TimeStampProvider for Box<dyn Signer> {
fn time_stamp_service_url(&self) -> Option<String> {
self.as_ref().time_authority_url()
}
fn time_stamp_request_headers(&self) -> Option<Vec<(String, String)>> {
self.as_ref().timestamp_request_headers()
}
fn time_stamp_request_body(
&self,
message: &[u8],
) -> std::result::Result<Vec<u8>, TimeStampError> {
Ok(self.as_ref().sign(message)?)
}
fn send_time_stamp_request(
&self,
message: &[u8],
) -> Option<std::result::Result<Vec<u8>, TimeStampError>> {
self.as_ref()
.send_timestamp_request(message)
.map(|r| Ok(r?))
}
}
#[cfg_attr(not(target_arch = "wasm32"), async_trait)]
#[cfg_attr(target_arch = "wasm32", async_trait(?Send))]
impl<T: ?Sized + AsyncSigner> AsyncSigner for Box<T> {
async fn sign(&self, data: Vec<u8>) -> Result<Vec<u8>> {
(**self).sign(data).await
}
fn alg(&self) -> SigningAlg {
(**self).alg()
}
fn certs(&self) -> Result<Vec<Vec<u8>>> {
(**self).certs()
}
fn reserve_size(&self) -> usize {
(**self).reserve_size()
}
fn time_authority_url(&self) -> Option<String> {
(**self).time_authority_url()
}
fn timestamp_request_headers(&self) -> Option<Vec<(String, String)>> {
(**self).timestamp_request_headers()
}
fn timestamp_request_body(&self, message: &[u8]) -> Result<Vec<u8>> {
(**self).timestamp_request_body(message)
}
async fn send_timestamp_request(&self, message: &[u8]) -> Option<Result<Vec<u8>>> {
(**self).send_timestamp_request(message).await
}
async fn ocsp_val(&self) -> Option<Vec<u8>> {
(**self).ocsp_val().await
}
fn direct_cose_handling(&self) -> bool {
(**self).direct_cose_handling()
}
fn dynamic_assertions(&self) -> Vec<Box<dyn AsyncDynamicAssertion>> {
(**self).dynamic_assertions()
}
fn async_raw_signer(&self) -> Option<Box<&dyn AsyncRawSigner>> {
(**self).async_raw_signer()
}
}
#[allow(dead_code)] pub(crate) struct RawSignerWrapper(pub(crate) Box<dyn RawSigner + Send + Sync>);
impl Signer for RawSignerWrapper {
fn sign(&self, data: &[u8]) -> Result<Vec<u8>> {
self.0.sign(data).map_err(|e| e.into())
}
fn alg(&self) -> SigningAlg {
self.0.alg()
}
fn certs(&self) -> Result<Vec<Vec<u8>>> {
self.0.cert_chain().map_err(|e| e.into())
}
fn reserve_size(&self) -> usize {
self.0.reserve_size()
}
fn ocsp_val(&self) -> Option<Vec<u8>> {
self.0.ocsp_response()
}
fn time_authority_url(&self) -> Option<String> {
self.0.time_stamp_service_url()
}
fn timestamp_request_headers(&self) -> Option<Vec<(String, String)>> {
self.0.time_stamp_request_headers()
}
fn timestamp_request_body(&self, message: &[u8]) -> Result<Vec<u8>> {
self.0
.time_stamp_request_body(message)
.map_err(|e| e.into())
}
fn send_timestamp_request(&self, message: &[u8]) -> Option<Result<Vec<u8>>> {
self.0
.send_time_stamp_request(message)
.map(|r| r.map_err(|e| e.into()))
}
fn raw_signer(&self) -> Option<Box<&dyn RawSigner>> {
Some(Box::new(&*self.0))
}
}