structured_cms/attribute_certificate/
ietf.rs1use super::{end, names, sequence, tag};
9use crate::attribute::Attribute;
10use crate::signer::required;
11use crate::{Error, ErrorCode, Result};
12use structured_asn1::memory::{OwnedVec, Work};
13use structured_asn1::{Element, Encoding, Oid, ScopedReader, Tag, universal};
14use structured_pkix::general_name::GeneralName;
15
16const FIELD: &str = "attributeCertificate.ietfAttrSyntax";
17
18pub const CHARGING_IDENTITY: Oid<'static> = Oid::from_bytes(&[43, 6, 1, 5, 5, 7, 10, 3]);
20pub const GROUP: Oid<'static> = Oid::from_bytes(&[43, 6, 1, 5, 5, 7, 10, 4]);
22
23#[derive(Debug, Clone, Copy, PartialEq, Eq)]
25pub enum Choice {
26 Octets,
28 Oid,
30 Utf8,
32}
33
34#[derive(Debug, Clone, Copy)]
36pub enum Value<'a> {
37 Octets(&'a [u8]),
39 Oid(Oid<'a>),
41 Utf8(&'a str),
43}
44impl Value<'_> {
45 #[must_use]
47 pub fn choice(self) -> Choice {
48 match self {
49 Self::Octets(_) => Choice::Octets,
50 Self::Oid(_) => Choice::Oid,
51 Self::Utf8(_) => Choice::Utf8,
52 }
53 }
54}
55
56#[derive(Debug, Clone, Copy)]
58pub struct Member<'a> {
59 pub element: Element<'a>,
61 pub value: Value<'a>,
63}
64
65#[derive(Debug)]
68pub struct IetfAttrSyntax<'a> {
69 element: Element<'a>,
70 authority: Option<OwnedVec<GeneralName<'a>>>,
71 authority_element: Option<Element<'a>>,
72 values: OwnedVec<Member<'a>>,
73 choice: Option<Choice>,
74}
75
76impl<'a> IetfAttrSyntax<'a> {
77 pub fn read(parent: &mut ScopedReader<'a, '_>) -> Result<Self> {
80 let element = required(parent, FIELD)?;
81 let reading = Self::read_element(parent, &element)?;
82 end(parent, FIELD)?;
83 Ok(reading)
84 }
85
86 pub fn read_element(parent: &ScopedReader<'a, '_>, element: &Element<'a>) -> Result<Self> {
90 let mut der = parent
91 .reread(element, Encoding::Der)
92 .map_err(|e| Error::encoding(e, FIELD))?;
93 let element = required(&mut der, FIELD)?;
94 tag(&element, sequence(), FIELD)?;
95 end(&der, FIELD)?;
96 let mut inside = der.enter(&element).map_err(|e| Error::encoding(e, FIELD))?;
97 let mut first = required(&mut inside, FIELD)?;
98 let (authority, authority_element) = if first.tag() == Tag::context(true, 0) {
99 let authority = names(&inside, &first, FIELD)?;
102 let encoded = first;
103 first = required(&mut inside, FIELD)?;
104 (Some(authority), Some(encoded))
105 } else {
106 (None, None)
107 };
108 tag(&first, sequence(), FIELD)?;
109 end(&inside, FIELD)?;
110 let mut members = inside
111 .enter(&first)
112 .map_err(|e| Error::encoding(e, FIELD))?;
113 let execution = inside.execution();
114 let mut values = execution.vector();
115 let mut choice = None;
116 while let Some(encoded) = members
117 .next_element()
118 .map_err(|e| Error::encoding(e, FIELD))?
119 {
120 let selected = match encoded.tag() {
121 t if t == Tag::primitive(universal::OCTET_STRING) => Choice::Octets,
122 t if t == Tag::primitive(universal::OID) => Choice::Oid,
123 t if t == Tag::primitive(universal::UTF8_STRING) => Choice::Utf8,
124 _ => {
125 return Err(Error::schema(
126 ErrorCode::UnexpectedTag,
127 FIELD,
128 encoded.span().start,
129 ));
130 }
131 };
132 if let Some(previous) = choice
135 && previous != selected
136 {
137 return Err(Error::schema(
138 ErrorCode::AttributeSyntax,
139 FIELD,
140 encoded.span().start,
141 ));
142 }
143 let value = match selected {
144 Choice::Octets => Value::Octets(encoded.contents()),
145 Choice::Oid => Value::Oid(
146 members
147 .oid(&encoded)
148 .map_err(|e| Error::encoding(e, FIELD))?,
149 ),
150 Choice::Utf8 => {
151 members
152 .charge(encoded.contents().len() as u64)
153 .map_err(|e| Error::encoding(e, FIELD))?;
154 Value::Utf8(core::str::from_utf8(encoded.contents()).map_err(|e| {
155 Error::schema(
156 ErrorCode::MalformedValue,
157 FIELD,
158 encoded.contents_span().start + e.valid_up_to() as u64,
159 )
160 })?)
161 }
162 };
163 values
164 .try_push(Member {
165 element: encoded,
166 value,
167 })
168 .map_err(|e| Error::resource(e, FIELD, encoded.span().start))?;
169 choice = Some(selected);
170 }
171 Ok(Self {
174 element,
175 authority,
176 authority_element,
177 values: values.into_owned(),
178 choice,
179 })
180 }
181
182 pub fn read_attribute<W: Work>(attribute: &Attribute<'a>, work: &W) -> Result<Self> {
187 let execution = attribute.query_in(work);
188 execution
191 .charge_work(17)
192 .map_err(|e| Error::resource(e, FIELD, attribute.span().start))?;
193 if attribute.kind() != GROUP && attribute.kind() != CHARGING_IDENTITY {
194 return Err(Error::schema(
195 ErrorCode::UnexpectedContentType,
196 FIELD,
197 attribute.span().start,
198 ));
199 }
200 if attribute.values().len() != 1 {
201 return Err(Error::schema(
202 ErrorCode::AttributeCardinality,
203 FIELD,
204 attribute.span().start,
205 ));
206 }
207 let mut reader = attribute
208 .value_reader_scoped(0, &execution, FIELD)?
209 .ok_or_else(|| {
210 Error::schema(
211 ErrorCode::AttributeCardinality,
212 FIELD,
213 attribute.span().start,
214 )
215 })?;
216 Self::read(&mut reader)
217 }
218
219 #[must_use]
221 pub fn element(&self) -> Element<'a> {
222 self.element
223 }
224 #[must_use]
226 pub fn authority(&self) -> Option<&[GeneralName<'a>]> {
227 self.authority.as_deref()
228 }
229 #[must_use]
231 pub fn authority_element(&self) -> Option<Element<'a>> {
232 self.authority_element
233 }
234 #[must_use]
237 pub fn values(&self) -> &[Member<'a>] {
238 &self.values
239 }
240 #[must_use]
242 pub fn choice(&self) -> Option<Choice> {
243 self.choice
244 }
245}