use {
crate::asn1::{
common::GeneralizedTime,
rfc3280::GeneralName,
rfc4210::PkiFreeText,
rfc5280::{AlgorithmIdentifier, Extensions},
rfc5652::ContentInfo,
},
bcder::{
decode::{Constructed, Malformed, Primitive, Source},
encode::{self, PrimitiveContent, Values},
ConstOid, Integer, OctetString, Oid, Tag,
},
};
pub const OID_CONTENT_TYPE_TST_INFO: ConstOid = Oid(&[42, 134, 72, 134, 247, 13, 1, 9, 16, 1, 4]);
pub const OID_TIME_STAMP_TOKEN: ConstOid = Oid(&[42, 134, 72, 134, 247, 13, 1, 9, 16, 2, 14]);
#[derive(Clone, Debug, Eq, PartialEq)]
pub struct TimeStampReq {
pub version: Integer,
pub message_imprint: MessageImprint,
pub req_policy: Option<TsaPolicyId>,
pub nonce: Option<Integer>,
pub cert_req: Option<bool>,
pub extensions: Option<Extensions>,
}
impl TimeStampReq {
pub fn take_from<S: Source>(cons: &mut Constructed<S>) -> Result<Self, S::Err> {
cons.take_sequence(|cons| {
let version = Integer::take_from(cons)?;
let message_imprint = MessageImprint::take_from(cons)?;
let req_policy = TsaPolicyId::take_opt_from(cons)?;
let nonce =
cons.take_opt_primitive_if(Tag::INTEGER, |prim| Integer::from_primitive(prim))?;
let cert_req = cons.take_opt_bool()?;
let extensions =
cons.take_opt_constructed_if(Tag::CTX_0, |cons| Extensions::take_from(cons))?;
Ok(Self {
version,
message_imprint,
req_policy,
nonce,
cert_req,
extensions,
})
})
}
pub fn encode_ref(&self) -> impl Values + '_ {
encode::sequence((
(&self.version).encode(),
self.message_imprint.encode_ref(),
if let Some(req_policy) = &self.req_policy {
Some(req_policy.encode_ref())
} else {
None
},
if let Some(nonce) = &self.nonce {
Some(nonce.encode())
} else {
None
},
if let Some(cert_req) = &self.cert_req {
Some(cert_req.encode_ref())
} else {
None
},
if let Some(extensions) = &self.extensions {
Some(extensions.encode_ref_as(Tag::CTX_0))
} else {
None
},
))
}
}
#[derive(Clone, Debug, Eq, PartialEq)]
pub struct MessageImprint {
pub hash_algorithm: AlgorithmIdentifier,
pub hashed_message: OctetString,
}
impl MessageImprint {
pub fn take_from<S: Source>(cons: &mut Constructed<S>) -> Result<Self, S::Err> {
cons.take_sequence(|cons| {
let hash_algorithm = AlgorithmIdentifier::take_from(cons)?;
let hashed_message = OctetString::take_from(cons)?;
Ok(Self {
hash_algorithm,
hashed_message,
})
})
}
pub fn encode_ref(&self) -> impl Values + '_ {
encode::sequence((
self.hash_algorithm.encode_ref(),
self.hashed_message.encode_ref(),
))
}
}
pub type TsaPolicyId = Oid;
#[derive(Clone, Debug, Eq, PartialEq)]
pub struct TimeStampResp {
pub status: PkiStatusInfo,
pub time_stamp_token: Option<TimeStampToken>,
}
impl TimeStampResp {
pub fn take_from<S: Source>(cons: &mut Constructed<S>) -> Result<Self, S::Err> {
cons.take_sequence(|cons| {
let status = PkiStatusInfo::take_from(cons)?;
let time_stamp_token = TimeStampToken::take_opt_from(cons)?;
Ok(Self {
status,
time_stamp_token,
})
})
}
pub fn encode_ref(&self) -> impl Values + '_ {
encode::sequence((
self.status.encode_ref(),
if let Some(time_stamp_token) = &self.time_stamp_token {
Some(time_stamp_token)
} else {
None
},
))
}
}
#[derive(Clone, Debug, Eq, PartialEq)]
pub struct PkiStatusInfo {
pub status: PkiStatus,
pub status_string: Option<PkiFreeText>,
pub fail_info: Option<PkiFailureInfo>,
}
impl PkiStatusInfo {
pub fn take_from<S: Source>(cons: &mut Constructed<S>) -> Result<Self, S::Err> {
cons.take_sequence(|cons| {
let status = PkiStatus::take_from(cons)?;
let status_string = PkiFreeText::take_opt_from(cons)?;
let fail_info = PkiFailureInfo::take_opt_from(cons)?;
Ok(Self {
status,
status_string,
fail_info,
})
})
}
pub fn encode_ref(&self) -> impl Values + '_ {
encode::sequence((
(&self.status).encode(),
if let Some(status_string) = &self.status_string {
Some(status_string.encode_ref())
} else {
None
},
if let Some(fail_info) = &self.fail_info {
Some(fail_info.encode())
} else {
None
},
))
}
}
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub enum PkiStatus {
Granted = 0,
GrantedWithMods = 1,
Rejection = 2,
Waiting = 3,
RevocationWarning = 4,
RevocationNotification = 5,
}
impl PkiStatus {
pub fn take_from<S: Source>(cons: &mut Constructed<S>) -> Result<Self, S::Err> {
match cons.take_primitive_if(Tag::INTEGER, Integer::i8_from_primitive)? {
0 => Ok(Self::Granted),
1 => Ok(Self::GrantedWithMods),
2 => Ok(Self::Rejection),
3 => Ok(Self::Waiting),
4 => Ok(Self::RevocationWarning),
5 => Ok(Self::RevocationNotification),
_ => Err(Malformed.into()),
}
}
pub fn encode(self) -> impl Values {
u8::from(self).encode()
}
}
impl From<PkiStatus> for u8 {
fn from(v: PkiStatus) -> u8 {
match v {
PkiStatus::Granted => 0,
PkiStatus::GrantedWithMods => 1,
PkiStatus::Rejection => 2,
PkiStatus::Waiting => 3,
PkiStatus::RevocationWarning => 4,
PkiStatus::RevocationNotification => 5,
}
}
}
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub enum PkiFailureInfo {
BadAlg = 0,
BadRequest = 1,
BadDataFormat = 5,
TimeNotAvailable = 14,
UnacceptedPolicy = 15,
UnacceptedExtension = 16,
AddInfoNotAvailable = 17,
SystemFailure = 25,
}
impl PkiFailureInfo {
pub fn take_opt_from<S: Source>(cons: &mut Constructed<S>) -> Result<Option<Self>, S::Err> {
cons.take_opt_primitive_if(Tag::INTEGER, Self::from_primitive)
}
pub fn take_from<S: Source>(cons: &mut Constructed<S>) -> Result<Self, S::Err> {
cons.take_primitive_if(Tag::INTEGER, Self::from_primitive)
}
pub fn from_primitive<S: Source>(prim: &mut Primitive<S>) -> Result<Self, S::Err> {
match Integer::i8_from_primitive(prim)? {
0 => Ok(Self::BadAlg),
1 => Ok(Self::BadRequest),
5 => Ok(Self::BadDataFormat),
14 => Ok(Self::TimeNotAvailable),
15 => Ok(Self::UnacceptedPolicy),
16 => Ok(Self::UnacceptedExtension),
17 => Ok(Self::AddInfoNotAvailable),
25 => Ok(Self::SystemFailure),
_ => Err(Malformed.into()),
}
}
pub fn encode(self) -> impl Values {
u8::from(self).encode()
}
}
impl From<PkiFailureInfo> for u8 {
fn from(v: PkiFailureInfo) -> u8 {
match v {
PkiFailureInfo::BadAlg => 0,
PkiFailureInfo::BadRequest => 1,
PkiFailureInfo::BadDataFormat => 5,
PkiFailureInfo::TimeNotAvailable => 14,
PkiFailureInfo::UnacceptedPolicy => 15,
PkiFailureInfo::UnacceptedExtension => 16,
PkiFailureInfo::AddInfoNotAvailable => 17,
PkiFailureInfo::SystemFailure => 25,
}
}
}
pub type TimeStampToken = ContentInfo;
#[derive(Clone, Debug, Eq, PartialEq)]
pub struct TstInfo {
pub version: Integer,
pub policy: TsaPolicyId,
pub message_imprint: MessageImprint,
pub serial_number: Integer,
pub gen_time: GeneralizedTime,
pub accuracy: Option<Accuracy>,
pub ordering: Option<bool>,
pub nonce: Option<Integer>,
pub tsa: Option<GeneralName>,
pub extensions: Option<Extensions>,
}
impl TstInfo {
pub fn take_from<S: Source>(cons: &mut Constructed<S>) -> Result<Self, S::Err> {
cons.take_sequence(|cons| {
let version = Integer::take_from(cons)?;
let policy = TsaPolicyId::take_from(cons)?;
let message_imprint = MessageImprint::take_from(cons)?;
let serial_number = Integer::take_from(cons)?;
let gen_time = GeneralizedTime::take_from(cons)?;
let accuracy = Accuracy::take_opt_from(cons)?;
let ordering = cons.take_opt_bool()?;
let nonce =
cons.take_opt_primitive_if(Tag::INTEGER, |prim| Integer::from_primitive(prim))?;
let tsa =
cons.take_opt_constructed_if(Tag::CTX_0, |cons| GeneralName::take_from(cons))?;
let extensions =
cons.take_opt_constructed_if(Tag::CTX_1, |cons| Extensions::take_from(cons))?;
Ok(Self {
version,
policy,
message_imprint,
serial_number,
gen_time,
accuracy,
ordering,
nonce,
tsa,
extensions,
})
})
}
pub fn encode_ref(&self) -> impl Values + '_ {
encode::sequence((
(&self.version).encode(),
self.policy.encode_ref(),
self.message_imprint.encode_ref(),
(&self.serial_number).encode(),
self.gen_time.encode_ref(),
if let Some(accuracy) = &self.accuracy {
Some(accuracy.encode_ref())
} else {
None
},
if let Some(ordering) = &self.ordering {
Some(ordering.encode_ref())
} else {
None
},
if let Some(nonce) = &self.nonce {
Some(nonce.encode())
} else {
None
},
if let Some(tsa) = &self.tsa {
Some(tsa.encode_ref().explicit(Tag::CTX_0))
} else {
None
},
if let Some(extensions) = &self.extensions {
Some(extensions.encode_ref_as(Tag::CTX_1))
} else {
None
},
))
}
}
#[derive(Clone, Debug, Eq, PartialEq)]
pub struct Accuracy {
pub seconds: Option<Integer>,
pub millis: Option<Integer>,
pub micros: Option<Integer>,
}
impl Accuracy {
pub fn take_opt_from<S: Source>(cons: &mut Constructed<S>) -> Result<Option<Self>, S::Err> {
cons.take_opt_sequence(|cons| Self::from_sequence(cons))
}
pub fn from_sequence<S: Source>(cons: &mut Constructed<S>) -> Result<Self, S::Err> {
let seconds =
cons.take_opt_primitive_if(Tag::INTEGER, |prim| Integer::from_primitive(prim))?;
let millis = cons.take_opt_constructed_if(Tag::CTX_0, |cons| Integer::take_from(cons))?;
let micros = cons.take_opt_constructed_if(Tag::CTX_1, |cons| Integer::take_from(cons))?;
Ok(Self {
seconds,
millis,
micros,
})
}
pub fn encode_ref(&self) -> impl Values + '_ {
encode::sequence((
if let Some(seconds) = &self.seconds {
Some(seconds.encode())
} else {
None
},
if let Some(millis) = &self.millis {
Some(millis.encode())
} else {
None
},
if let Some(micros) = &self.micros {
Some(micros.encode())
} else {
None
},
))
}
}