1use super::{
2 ALT_SIGNATURE_ALGORITHM, ALT_SIGNATURE_VALUE, FIELD, Fault, SUBJECT_ALT_PUBLIC_KEY_INFO,
3 terminal,
4};
5use crate::algorithm::{self, AlgorithmIdentifier};
6use crate::error::Located;
7use crate::signature::SignatureValue;
8use crate::{Error, ErrorCode, Extensions, PublicKeyInfo, Result};
9use structured_asn1::memory::Work;
10use structured_asn1::{Element, ScopedReader, Span};
11
12#[derive(Debug)]
15pub struct Component<'a, T> {
16 span: Option<Span>,
17 critical: Option<bool>,
18 bytes: Option<&'a [u8]>,
19 value: core::result::Result<Option<T>, Fault>,
20 field: &'static str,
21 at: u64,
22}
23impl<'a, T: Copy> Component<'a, T> {
24 pub(super) fn absent(field: &'static str) -> Self {
25 Self {
26 span: None,
27 critical: None,
28 bytes: None,
29 value: Ok(None),
30 field,
31 at: 0,
32 }
33 }
34 #[must_use]
36 pub fn span(&self) -> Option<Span> {
37 self.span
38 }
39 #[must_use]
41 pub fn critical(&self) -> Option<bool> {
42 self.critical
43 }
44 #[must_use]
46 pub fn as_bytes(&self) -> Option<&'a [u8]> {
47 self.bytes
48 }
49 pub fn reading(&self) -> core::result::Result<Option<T>, Fault> {
51 self.value
52 }
53 pub(super) fn require(&self) -> Result<T> {
54 match self.value {
55 Ok(Some(value)) => Ok(value),
56 Ok(None) => Err(Error::new(ErrorCode::MissingField, self.field, self.at)),
57 Err(fault) => Err(fault.error()),
58 }
59 }
60 pub(super) fn read(
61 span: Span,
62 critical: Option<bool>,
63 bytes: &'a [u8],
64 field: &'static str,
65 action: impl FnOnce() -> Result<T>,
66 ) -> Result<Self> {
67 let value = match action() {
68 Ok(value) => Ok(Some(value)),
69 Err(error) if terminal(&error) => return Err(error),
70 Err(error) => Err(Fault::of(&error)),
71 };
72 Ok(Self {
73 span: Some(span),
74 critical,
75 bytes: Some(bytes),
76 value,
77 field,
78 at: span.start,
79 })
80 }
81}
82
83#[derive(Debug)]
85pub struct Components<'a> {
86 pub key: Component<'a, PublicKeyInfo<'a>>,
88 pub algorithm: Component<'a, AlgorithmIdentifier<'a>>,
90 pub signature: Component<'a, SignatureValue<'a>>,
92}
93impl<'a> Components<'a> {
94 pub(super) fn empty(at: u64) -> Self {
95 let mut result = Self {
96 key: Component::absent("hybrid.subjectAltPublicKeyInfo"),
97 algorithm: Component::absent("hybrid.altSignatureAlgorithm"),
98 signature: Component::absent("hybrid.altSignatureValue"),
99 };
100 result.key.at = at;
101 result.algorithm.at = at;
102 result.signature.at = at;
103 result
104 }
105 pub(super) fn signature_fields(
106 &self,
107 ) -> Result<(AlgorithmIdentifier<'a>, SignatureValue<'a>, Span)> {
108 let algorithm = self.algorithm.require()?;
109 let signature = self.signature.require()?;
110 Ok((
111 algorithm,
112 signature,
113 self.signature
114 .span
115 .expect("a decoded signature has a source"),
116 ))
117 }
118}
119
120pub(super) fn extensions<'a, W: Work>(
121 extensions: &Extensions<'a>,
122 work: &W,
123 at: u64,
124) -> Result<Components<'a>> {
125 work.charge_work(1)
126 .map_err(|e| Error::resource(e, FIELD, at))?;
127 let mut output = Components::empty(at);
128 for extension in extensions.iter(work) {
129 let extension = extension?;
130 let kind = extension.kind();
131 super::identifier_work(kind, work, extension.span().start)?;
133 if kind == SUBJECT_ALT_PUBLIC_KEY_INFO {
134 output.key = Component::read(
135 extension.span(),
136 Some(extension.is_critical()),
137 extension.value(),
138 "hybrid.subjectAltPublicKeyInfo",
139 || {
140 let mut reader = extension.reader_scoped(work).field(FIELD)?;
141 let element = one(&mut reader)?;
142 PublicKeyInfo::read_element(&reader, &element, FIELD)
143 },
144 )?;
145 } else if kind == ALT_SIGNATURE_ALGORITHM {
146 output.algorithm = Component::read(
147 extension.span(),
148 Some(extension.is_critical()),
149 extension.value(),
150 "hybrid.altSignatureAlgorithm",
151 || {
152 let mut reader = extension.reader_scoped(work).field(FIELD)?;
153 let element = one(&mut reader)?;
154 algorithm::read(&reader, &element, FIELD)
155 },
156 )?;
157 } else if kind == ALT_SIGNATURE_VALUE {
158 output.signature = Component::read(
159 extension.span(),
160 Some(extension.is_critical()),
161 extension.value(),
162 "hybrid.altSignatureValue",
163 || {
164 let mut reader = extension.reader_scoped(work).field(FIELD)?;
165 let value = SignatureValue::read(&mut reader, FIELD)?;
166 end(&reader)?;
167 Ok(value)
168 },
169 )?;
170 }
171 }
172 Ok(output)
173}
174
175pub(super) fn one<'a>(reader: &mut ScopedReader<'a, '_>) -> Result<Element<'a>> {
176 let value = reader
177 .next_element()
178 .field(FIELD)?
179 .ok_or_else(|| Error::new(ErrorCode::MissingField, FIELD, reader.offset()))?;
180 end(reader)?;
181 Ok(value)
182}
183pub(super) fn end(reader: &ScopedReader<'_, '_>) -> Result<()> {
184 if !reader.is_empty() {
185 return Err(Error::new(ErrorCode::TrailingData, FIELD, reader.offset()));
186 }
187 Ok(())
188}