use std::collections::HashMap;
use async_generic::async_generic;
use serde::{Deserialize, Serialize};
use serde_bytes::ByteBuf;
use crate::{
assertion::{Assertion, AssertionBase, AssertionCbor},
assertions::labels,
crypto::cose::CertificateTrustPolicy,
error::Result,
http::{AsyncHttpResolver, SyncHttpResolver},
status_tracker::StatusTracker,
Error,
};
#[derive(Serialize, Deserialize, Default, Debug, PartialEq, Eq)]
pub struct TimeStamp(pub HashMap<String, ByteBuf>);
impl TimeStamp {
pub const LABEL: &'static str = labels::TIMESTAMP;
pub fn new() -> Self {
TimeStamp(HashMap::new())
}
pub fn add_timestamp(&mut self, manifest_id: &str, timestamp: &[u8]) {
self.0
.insert(manifest_id.to_string(), ByteBuf::from(timestamp.to_vec()));
}
pub fn get_timestamp(&self, manifest_id: &str) -> Option<&[u8]> {
self.0.get(manifest_id).map(|buf| buf.as_ref())
}
#[async_generic(async_signature(
&mut self,
tsa_url: &str,
manifest_id: &str,
signature: &[u8],
http_resolver: &impl AsyncHttpResolver,
))]
pub(crate) fn refresh_timestamp(
&mut self,
tsa_url: &str,
manifest_id: &str,
signature: &[u8],
http_resolver: &impl SyncHttpResolver,
) -> Result<()> {
let timestamp_token = if _sync {
TimeStamp::send_timestamp_token_request(tsa_url, signature, http_resolver)?
} else {
TimeStamp::send_timestamp_token_request_async(tsa_url, signature, http_resolver).await?
};
self.0
.insert(manifest_id.to_owned(), ByteBuf::from(timestamp_token));
Ok(())
}
#[async_generic(async_signature(
tsa_url: &str,
message: &[u8],
http_resolver: &impl AsyncHttpResolver,
))]
pub(crate) fn send_timestamp_token_request(
tsa_url: &str,
message: &[u8],
http_resolver: &impl SyncHttpResolver,
) -> Result<Vec<u8>> {
let body = crate::crypto::time_stamp::default_rfc3161_message(message)?;
let headers = None;
let bytes = if _sync {
crate::crypto::time_stamp::default_rfc3161_request(
tsa_url,
headers,
&body,
message,
http_resolver,
)
} else {
crate::crypto::time_stamp::default_rfc3161_request_async(
tsa_url,
headers,
&body,
message,
http_resolver,
)
.await
}
.map_err(|err| Error::OtherError(format!("timestamp token not found: {err:?}").into()))?;
let ctp = CertificateTrustPolicy::passthrough();
let mut tracker = StatusTracker::default();
if _sync {
crate::crypto::time_stamp::verify_time_stamp(
&bytes,
message,
&ctp,
&mut tracker,
false,
)?;
} else {
crate::crypto::time_stamp::verify_time_stamp_async(
&bytes,
message,
&ctp,
&mut tracker,
false,
)
.await?;
}
let token =
crate::crypto::cose::timestamptoken_from_timestamprsp(&bytes).map_err(|err| {
Error::OtherError(format!("timestamp token not found: {err:?}").into())
})?;
Ok(token)
}
}
impl AsRef<HashMap<String, ByteBuf>> for TimeStamp {
fn as_ref(&self) -> &HashMap<String, ByteBuf> {
&self.0
}
}
impl AssertionCbor for TimeStamp {}
impl AssertionBase for TimeStamp {
const LABEL: &'static str = Self::LABEL;
fn to_assertion(&self) -> Result<Assertion> {
Self::to_cbor_assertion(self)
}
fn from_assertion(assertion: &Assertion) -> Result<Self> {
Self::from_cbor_assertion(assertion)
}
}