1use super::{Basis, ByteOrder, Octets, Profile, identify};
4use crate::algorithm::{AlgorithmIdentifier, Producer};
5use crate::error::Located;
6use crate::{Error, ErrorCode, Result};
7use structured_asn1::memory::{Execution, Work};
8use structured_asn1::{Element, Encoding, Integer, Oid, ScopedReader, Span, Tag, universal};
9
10const FIELD: &str = "dstu4145.parameters";
11
12#[derive(Debug, Clone, Copy)]
14pub struct IntegerField<'a> {
15 span: Span,
16 value: Integer<'a>,
17}
18
19impl<'a> IntegerField<'a> {
20 #[must_use]
22 pub const fn value(self) -> Integer<'a> {
23 self.value
24 }
25
26 #[must_use]
28 pub const fn span(self) -> Span {
29 self.span
30 }
31}
32
33#[derive(Debug, Clone, Copy, PartialEq, Eq)]
35pub enum Reduction {
36 Trinomial(u32),
38 Pentanomial {
40 k: u32,
42 j: u32,
44 l: u32,
46 },
47 OptimalNormal,
49}
50
51#[derive(Debug, Clone, Copy)]
53pub struct NamedCurve<'a> {
54 element: Element<'a>,
55 identifier: Oid<'a>,
56 known: Option<(Basis, u32)>,
57}
58
59impl<'a> NamedCurve<'a> {
60 #[must_use]
62 pub const fn identifier(self) -> Oid<'a> {
63 self.identifier
64 }
65
66 #[must_use]
68 pub const fn element(self) -> Element<'a> {
69 self.element
70 }
71
72 #[must_use]
75 pub const fn known(self) -> Option<(Basis, u32)> {
76 self.known
77 }
78}
79
80#[derive(Debug, Clone, Copy)]
82pub struct ExplicitCurve<'a> {
83 element: Element<'a>,
84 degree: IntegerField<'a>,
85 degree_value: u32,
86 field: Span,
87 reduction: Reduction,
88 a: IntegerField<'a>,
89 b: Octets<'a>,
90 order: IntegerField<'a>,
91 base_point: Octets<'a>,
92}
93
94impl<'a> ExplicitCurve<'a> {
95 #[must_use]
97 pub const fn element(self) -> Element<'a> {
98 self.element
99 }
100 #[must_use]
102 pub const fn field_span(self) -> Span {
103 self.field
104 }
105 #[must_use]
107 pub const fn degree(self) -> IntegerField<'a> {
108 self.degree
109 }
110 #[must_use]
112 pub const fn degree_value(self) -> u32 {
113 self.degree_value
114 }
115 #[must_use]
117 pub const fn reduction(self) -> Reduction {
118 self.reduction
119 }
120 #[must_use]
122 pub const fn a(self) -> IntegerField<'a> {
123 self.a
124 }
125 #[must_use]
127 pub const fn b(self) -> Octets<'a> {
128 self.b
129 }
130 #[must_use]
132 pub const fn order(self) -> IntegerField<'a> {
133 self.order
134 }
135 #[must_use]
137 pub const fn base_point(self) -> Octets<'a> {
138 self.base_point
139 }
140}
141
142#[derive(Debug, Clone, Copy)]
144pub enum Curve<'a> {
145 Named(NamedCurve<'a>),
147 Explicit(ExplicitCurve<'a>),
149}
150
151impl Curve<'_> {
152 #[must_use]
154 pub const fn degree(&self) -> Option<u32> {
155 match self {
156 Self::Named(curve) => match curve.known {
157 Some((_, degree)) => Some(degree),
158 None => None,
159 },
160 Self::Explicit(curve) => Some(curve.degree_value),
161 }
162 }
163}
164
165#[derive(Debug, Clone, Copy)]
167pub struct Parameters<'a> {
168 element: Element<'a>,
169 curve: Curve<'a>,
170 dke: Option<Element<'a>>,
171 producer: Producer<'a>,
172}
173
174impl<'a> Parameters<'a> {
175 #[must_use]
178 pub const fn execution_origin(self) -> Producer<'a> {
179 self.producer
180 }
181 #[must_use]
183 pub const fn element(self) -> Element<'a> {
184 self.element
185 }
186 #[must_use]
188 pub const fn curve(self) -> Curve<'a> {
189 self.curve
190 }
191 #[must_use]
195 pub const fn dke(self) -> Option<Element<'a>> {
196 self.dke
197 }
198 #[must_use]
200 pub fn execution_in<'q, W: Work>(&self, current: &'q W) -> Execution<'q>
201 where
202 'a: 'q,
203 {
204 self.producer.execution_in(current)
205 }
206}
207
208pub fn read_parameters<'a, W: Work>(
220 identifier: AlgorithmIdentifier<'a>,
221 current: &W,
222) -> Result<Option<Parameters<'a>>> {
223 let profile = identify(identifier, current)?
224 .ok_or_else(|| Error::new(ErrorCode::UnexpectedField, FIELD, identifier.offset()))?;
225 read_known(identifier, profile, current)
226}
227
228pub(crate) fn read_known<'a, W: Work>(
229 identifier: AlgorithmIdentifier<'a>,
230 profile: Profile,
231 current: &W,
232) -> Result<Option<Parameters<'a>>> {
233 let Some(source) = identifier.parameters_nested() else {
234 return Ok(None);
235 };
236 let (reader, element) = source.open(current, FIELD)?;
237 let value = if reader.encoding().is_der() {
238 fields(&reader, element, profile, identifier.execution_origin())?
239 } else {
240 let mut strict = reader.reread(&element, Encoding::Der).field(FIELD)?;
241 let element = strict
242 .next_element()
243 .field(FIELD)?
244 .ok_or_else(|| Error::new(ErrorCode::MissingField, FIELD, strict.offset()))?;
245 fields(&strict, element, profile, identifier.execution_origin())?
246 };
247 Ok(Some(value))
248}
249
250fn fields<'a>(
251 reader: &ScopedReader<'a, '_>,
252 element: Element<'a>,
253 profile: Profile,
254 producer: Producer<'a>,
255) -> Result<Parameters<'a>> {
256 require_tag(element, Tag::constructed(universal::SEQUENCE))?;
257 let mut inside = reader.enter(&element).field(FIELD)?;
258 let first = next(&mut inside)?;
259 let curve = if first.tag() == Tag::primitive(universal::OID) {
260 let identifier = inside.oid(&first).field(FIELD)?;
261 inside
262 .charge(identifier.as_bytes().len() as u64 + 1)
263 .field(FIELD)?;
264 let known = named(identifier);
265 if let Some((basis, _)) = known
266 && basis != profile.basis()
267 {
268 return Err(Error::new(
269 ErrorCode::MalformedValue,
270 FIELD,
271 first.span().start,
272 ));
273 }
274 Curve::Named(NamedCurve {
275 element: first,
276 identifier,
277 known,
278 })
279 } else {
280 Curve::Explicit(explicit(&inside, first, profile)?)
281 };
282 let dke = inside.next_element().field(FIELD)?;
283 if let Some(dke) = dke {
284 require_tag(dke, Tag::primitive(universal::OCTET_STRING))?;
285 if dke.contents().len() != 64 {
286 return Err(Error::new(
287 ErrorCode::MalformedValue,
288 FIELD,
289 dke.span().start,
290 ));
291 }
292 }
293 exhausted(&inside)?;
294 Ok(Parameters {
295 element,
296 curve,
297 dke,
298 producer,
299 })
300}
301
302fn explicit<'a>(
303 reader: &ScopedReader<'a, '_>,
304 element: Element<'a>,
305 profile: Profile,
306) -> Result<ExplicitCurve<'a>> {
307 require_tag(element, Tag::constructed(universal::SEQUENCE))?;
308 let mut inside = reader.enter(&element).field(FIELD)?;
309 let field = next(&mut inside)?;
310 if field.tag() == Tag::context(true, 0) {
311 let mut version = inside.enter(&field).field(FIELD)?;
312 let value = integer(&mut version)?;
313 exhausted(&version)?;
314 let value = number(&version, value)?;
315 let code = if value == 0 {
318 ErrorCode::DefaultWritten
319 } else {
320 ErrorCode::UnsupportedVersion
321 };
322 return Err(Error::new(code, FIELD, field.span().start));
323 }
324 require_tag(field, Tag::constructed(universal::SEQUENCE))?;
325 let mut binary = inside.enter(&field).field(FIELD)?;
326 let degree = integer(&mut binary)?;
327 let degree_value = number(&binary, degree)?;
328 if degree_value == 0 {
329 return Err(Error::new(
330 ErrorCode::MalformedValue,
331 FIELD,
332 degree.span.start,
333 ));
334 }
335 let reduction = if profile.basis() == Basis::OptimalNormal {
336 exhausted(&binary)?;
337 Reduction::OptimalNormal
338 } else {
339 let written = next(&mut binary)?;
340 let reduction = if written.tag() == Tag::primitive(universal::INTEGER) {
341 let k = integer_element(&binary, written)?;
342 let k = number(&binary, k)?;
343 if k == 0 || k >= degree_value {
344 return Err(Error::new(
345 ErrorCode::MalformedValue,
346 FIELD,
347 written.span().start,
348 ));
349 }
350 Reduction::Trinomial(k)
351 } else {
352 require_tag(written, Tag::constructed(universal::SEQUENCE))?;
353 let mut terms = binary.enter(&written).field(FIELD)?;
354 let k = integer(&mut terms)?;
355 let k = number(&terms, k)?;
356 let j = integer(&mut terms)?;
357 let j = number(&terms, j)?;
358 let l = integer(&mut terms)?;
359 let l = number(&terms, l)?;
360 exhausted(&terms)?;
361 if k == 0 || k >= j || j >= l || l >= degree_value {
362 return Err(Error::new(
363 ErrorCode::MalformedValue,
364 FIELD,
365 written.span().start,
366 ));
367 }
368 Reduction::Pentanomial { k, j, l }
369 };
370 exhausted(&binary)?;
371 reduction
372 };
373 let a = integer(&mut inside)?;
374 if number(&inside, a)? > 1 {
375 return Err(Error::new(ErrorCode::MalformedValue, FIELD, a.span.start));
376 }
377 let b_element = next(&mut inside)?;
378 let b = field_octets(&inside, b_element, degree_value, profile.byte_order())?;
379 let order = integer(&mut inside)?;
380 inside.charge(1).field(FIELD)?;
381 if order.value.as_bytes() == [0] {
382 return Err(Error::new(
383 ErrorCode::MalformedValue,
384 FIELD,
385 order.span.start,
386 ));
387 }
388 let point_element = next(&mut inside)?;
389 let base_point = field_octets(&inside, point_element, degree_value, profile.byte_order())?;
390 exhausted(&inside)?;
391 Ok(ExplicitCurve {
392 element,
393 degree,
394 degree_value,
395 field: field.span(),
396 reduction,
397 a,
398 b,
399 order,
400 base_point,
401 })
402}
403
404pub(crate) fn field_octets<'a>(
405 reader: &ScopedReader<'a, '_>,
406 element: Element<'a>,
407 degree: u32,
408 byte_order: ByteOrder,
409) -> Result<Octets<'a>> {
410 require_tag(element, Tag::primitive(universal::OCTET_STRING))?;
411 let bytes = element.contents();
412 reader.charge(1).field(FIELD)?;
413 if degree == 0 || bytes.len() as u64 != u64::from(degree).div_ceil(8) {
414 return Err(Error::new(
415 ErrorCode::MalformedValue,
416 FIELD,
417 element.span().start,
418 ));
419 }
420 let unused = (8 - degree % 8) % 8;
421 let top = match byte_order {
422 ByteOrder::LittleEndian => bytes[bytes.len() - 1],
423 ByteOrder::BigEndian => bytes[0],
424 };
425 if unused != 0 && top >> (8 - unused) != 0 {
426 return Err(Error::new(
427 ErrorCode::MalformedValue,
428 FIELD,
429 element.contents_span().start,
430 ));
431 }
432 Ok(Octets::new(
433 bytes,
434 byte_order,
435 element.contents_span().start,
436 ))
437}
438
439fn named(identifier: Oid<'_>) -> Option<(Basis, u32)> {
440 let (basis, index) = match identifier.as_bytes() {
441 [0x2a, 0x86, 0x24, 2, 1, 1, 1, 1, 3, 1, basis, 2, index]
442 | [
443 0x2a,
444 0x86,
445 0x24,
446 2,
447 1,
448 1,
449 1,
450 1,
451 3,
452 6,
453 1..=3,
454 basis,
455 2,
456 index,
457 ] => (*basis, *index),
458 _ => return None,
459 };
460 let (basis, degrees): (_, &[u32]) = match basis {
463 1 => (
464 Basis::Polynomial,
465 &[163, 167, 173, 179, 191, 233, 257, 307, 367, 431],
466 ),
467 2 => (Basis::OptimalNormal, &[173, 179, 191, 233, 431]),
468 _ => return None,
469 };
470 degrees
471 .get(usize::from(index))
472 .map(|degree| (basis, *degree))
473}
474
475fn require_tag(element: Element<'_>, tag: Tag) -> Result<()> {
476 if element.tag() != tag {
477 return Err(Error::new(
478 ErrorCode::Encoding(structured_asn1::ErrorCode::UnexpectedTag),
479 FIELD,
480 element.span().start,
481 ));
482 }
483 Ok(())
484}
485fn next<'a>(reader: &mut ScopedReader<'a, '_>) -> Result<Element<'a>> {
486 reader
487 .next_element()
488 .field(FIELD)?
489 .ok_or_else(|| Error::new(ErrorCode::MissingField, FIELD, reader.offset()))
490}
491fn exhausted(reader: &ScopedReader<'_, '_>) -> Result<()> {
492 if !reader.is_empty() {
493 return Err(Error::new(ErrorCode::TrailingData, FIELD, reader.offset()));
494 }
495 Ok(())
496}
497fn integer<'a>(reader: &mut ScopedReader<'a, '_>) -> Result<IntegerField<'a>> {
498 let element = next(reader)?;
499 integer_element(reader, element)
500}
501fn integer_element<'a>(
502 reader: &ScopedReader<'a, '_>,
503 element: Element<'a>,
504) -> Result<IntegerField<'a>> {
505 require_tag(element, Tag::primitive(universal::INTEGER))?;
506 let value = reader.integer(&element).field(FIELD)?;
507 reader.charge(1).field(FIELD)?;
508 if value.is_negative() {
509 return Err(Error::new(
510 ErrorCode::MalformedValue,
511 FIELD,
512 element.span().start,
513 ));
514 }
515 Ok(IntegerField {
516 span: element.span(),
517 value,
518 })
519}
520fn number(reader: &ScopedReader<'_, '_>, value: IntegerField<'_>) -> Result<u32> {
521 reader
522 .charge(value.value.as_bytes().len() as u64)
523 .field(FIELD)?;
524 value
525 .value
526 .as_u32()
527 .ok_or_else(|| Error::new(ErrorCode::ValueTooLarge, FIELD, value.span.start))
528}