structured_pkix/algorithm/
dstu4145.rs1use super::{AlgorithmIdentifier, digest};
12use crate::{Error, Result};
13use structured_asn1::memory::Work;
14
15pub mod parameters;
16pub use parameters::{Curve, ExplicitCurve, NamedCurve, Parameters, Reduction, read_parameters};
17
18#[derive(Debug, Clone, Copy, PartialEq, Eq)]
20pub enum Basis {
21 Polynomial,
23 OptimalNormal,
25}
26
27#[derive(Debug, Clone, Copy, PartialEq, Eq)]
29pub enum ByteOrder {
30 LittleEndian,
32 BigEndian,
34}
35
36#[derive(Debug, Clone, Copy, PartialEq, Eq)]
38pub struct Profile {
39 digest: digest::Algorithm,
40 basis: Basis,
41 byte_order: ByteOrder,
42}
43
44impl Profile {
45 #[must_use]
47 pub const fn digest(self) -> digest::Algorithm {
48 self.digest
49 }
50
51 #[must_use]
53 pub const fn basis(self) -> Basis {
54 self.basis
55 }
56
57 #[must_use]
59 pub const fn byte_order(self) -> ByteOrder {
60 self.byte_order
61 }
62}
63
64pub fn identify<W: Work>(
73 identifier: AlgorithmIdentifier<'_>,
74 execution: &W,
75) -> Result<Option<Profile>> {
76 let bytes = identifier.algorithm().as_bytes();
77 identifier
78 .query_in(execution)
79 .charge_work(bytes.len() as u64 + 1)
80 .map_err(|reason| Error::resource(reason, identifier.field, identifier.offset()))?;
81 Ok(from_octets(bytes))
82}
83
84pub(super) fn from_octets(bytes: &[u8]) -> Option<Profile> {
86 use digest::Algorithm::{Gost34311, Kupyna256, Kupyna384, Kupyna512};
87 let (digest, basis, tail) = match bytes {
88 [0x2a, 0x86, 0x24, 2, 1, 1, 1, 1, 3, 1, basis, tail @ ..] => (Gost34311, basis, tail),
89 [
90 0x2a,
91 0x86,
92 0x24,
93 2,
94 1,
95 1,
96 1,
97 1,
98 3,
99 6,
100 hash,
101 basis,
102 tail @ ..,
103 ] => {
104 let digest = match hash {
105 1 => Kupyna256,
106 2 => Kupyna384,
107 3 => Kupyna512,
108 _ => return None,
109 };
110 (digest, basis, tail)
111 }
112 _ => return None,
113 };
114 let basis = match basis {
115 1 => Basis::Polynomial,
116 2 => Basis::OptimalNormal,
117 _ => return None,
118 };
119 let byte_order = match tail {
120 [] => ByteOrder::LittleEndian,
121 [1, 1] => ByteOrder::BigEndian,
122 _ => return None,
123 };
124 Some(Profile {
125 digest,
126 basis,
127 byte_order,
128 })
129}
130
131#[derive(Debug, Clone, Copy)]
137pub struct Octets<'a> {
138 bytes: &'a [u8],
139 byte_order: ByteOrder,
140 offset: u64,
141}
142
143impl<'a> Octets<'a> {
144 pub(crate) const fn new(bytes: &'a [u8], byte_order: ByteOrder, offset: u64) -> Self {
145 Self {
146 bytes,
147 byte_order,
148 offset,
149 }
150 }
151
152 #[must_use]
154 pub const fn as_bytes(self) -> &'a [u8] {
155 self.bytes
156 }
157
158 #[must_use]
160 pub const fn byte_order(self) -> ByteOrder {
161 self.byte_order
162 }
163
164 #[must_use]
166 pub const fn offset(self) -> u64 {
167 self.offset
168 }
169
170 pub fn big_endian(self) -> impl ExactSizeIterator<Item = u8> + DoubleEndedIterator + 'a {
172 let bytes = self.bytes;
173 (0..bytes.len()).map(move |index| match self.byte_order {
174 ByteOrder::BigEndian => bytes[index],
175 ByteOrder::LittleEndian => bytes[bytes.len() - 1 - index],
176 })
177 }
178}