structured_pkix/key/dsa.rs
1//! Borrowed DSA key components, before bigint or group validation.
2//!
3//! RFC 3279 §2.3.2 carries optional `Dss-Parms ::= SEQUENCE { p INTEGER,
4//! q INTEGER, g INTEGER }` and a DER INTEGER `y` inside subjectPublicKey.
5//! [`read`] preserves these sources and effective parameter inheritance;
6//! success does not establish a usable DSA group, key strength or signature.
7//! <https://www.rfc-editor.org/rfc/rfc3279#section-2.3.2>
8
9use super::same_oid;
10use crate::error::{Error, ErrorCode, Located, Result};
11use crate::path::WorkingKey;
12use structured_asn1::memory::Work;
13use structured_asn1::{Element, Encoding, Integer, Oid, ScopedReader, Tag, universal};
14
15const OID: Oid<'static> = Oid::from_bytes(&[0x2a, 0x86, 0x48, 0xce, 0x38, 0x04, 0x01]);
16const FIELD: &str = "subjectPublicKey.dsa";
17const PARAMETERS: &str = "subjectPublicKeyInfo.algorithm.parameters";
18
19/// A nonnegative component with its original INTEGER and location.
20///
21/// Zero is inspectable, not a valid DSA component. Group and range validation
22/// belongs to the selected backend, before arithmetic or key acceptance.
23#[derive(Debug, Clone, Copy)]
24pub struct Component<'a> {
25 element: Element<'a>,
26 integer: Integer<'a>,
27}
28
29impl<'a> Component<'a> {
30 /// Borrowed unsigned magnitude, excluding a required positive sign octet.
31 /// Zero is represented by the single octet `0x00`.
32 #[must_use]
33 pub fn as_bytes(&self) -> &'a [u8] {
34 match self.integer.as_bytes() {
35 [0, rest @ ..] if !rest.is_empty() => rest,
36 bytes => bytes,
37 }
38 }
39
40 /// Original minimal two's-complement encoding, including any sign octet.
41 #[must_use]
42 pub fn integer(&self) -> Integer<'a> {
43 self.integer
44 }
45
46 /// Original whole INTEGER element in its source's coordinates.
47 #[must_use]
48 pub fn element(&self) -> Element<'a> {
49 self.element
50 }
51}
52
53/// The domain parameters in force, still borrowing their original source.
54#[derive(Debug, Clone, Copy)]
55pub struct Parameters<'a> {
56 element: Element<'a>,
57 p: Component<'a>,
58 q: Component<'a>,
59 g: Component<'a>,
60 inherited: bool,
61}
62
63impl<'a> Parameters<'a> {
64 /// The encoded prime candidate; primality has not been established.
65 #[must_use]
66 pub fn p(&self) -> &Component<'a> {
67 &self.p
68 }
69
70 /// The encoded subgroup-order candidate; no group check is implied.
71 #[must_use]
72 pub fn q(&self) -> &Component<'a> {
73 &self.q
74 }
75
76 /// The encoded generator candidate; no range or order check is implied.
77 #[must_use]
78 pub fn g(&self) -> &Component<'a> {
79 &self.g
80 }
81
82 /// The whole original Dss-Parms SEQUENCE, including its header.
83 #[must_use]
84 pub fn element(&self) -> Element<'a> {
85 self.element
86 }
87
88 /// Whether these parameters came from an authority above this key.
89 #[must_use]
90 pub fn is_inherited(&self) -> bool {
91 self.inherited
92 }
93}
94
95/// The subject's original DSA public component and effective parameters.
96#[derive(Debug, Clone, Copy)]
97pub struct PublicKey<'a> {
98 y: Component<'a>,
99 parameters: Option<Parameters<'a>>,
100}
101
102impl<'a> PublicKey<'a> {
103 /// Original unsigned public component; no mathematical validity is claimed.
104 #[must_use]
105 pub fn y(&self) -> &Component<'a> {
106 &self.y
107 }
108
109 /// Effective parameters, or None when neither written nor inherited.
110 /// The caller needs independently supplied parameters before verification
111 /// in the latter case (RFC 3279 §2.3.2).
112 #[must_use]
113 pub fn parameters(&self) -> Option<&Parameters<'a>> {
114 self.parameters.as_ref()
115 }
116}
117
118/// Reads DSA structure under the current execution and original source ceilings.
119///
120/// Accepts only id-dsa. Written NULL is malformed, even if the generic path
121/// state carries inherited parameters. Absent parameters remain distinguishable
122/// from supplied ones. Parameters use their original encoding; `y` must be DER
123/// even under a BER parent. Reader metadata is funded before allocation; all
124/// returned views borrow original bytes and retain no storage or execution.
125///
126/// # Errors
127/// Reports another algorithm, malformed unsigned components, missing/extra
128/// fields, encoding errors and original located resource failures separately.
129/// This does not check primes, group membership, strength or signature validity.
130///
131/// # Examples
132/// ```
133/// use std::sync::Arc;
134/// use structured_asn1::{Parser, memory::{Memory, MemoryAccount}};
135/// use structured_pkix::{PublicKeyInfo, key::dsa, path::WorkingKey};
136/// let memory = Memory::new(Arc::new(MemoryAccount::new(4096, 4096)));
137/// let parser = Parser::der(memory.clone());
138/// // id-dsa, omitted parameters; subjectPublicKey contains INTEGER 7.
139/// let bytes = b"\x30\x11\x30\x09\x06\x07\x2a\x86\x48\xce\x38\x04\x01\x03\x04\x00\x02\x01\x07";
140/// let mut reader = parser.read(bytes, 400).unwrap();
141/// let element = reader.next_element().unwrap().unwrap();
142/// let info = PublicKeyInfo::read_element(&reader, &element, "key")?;
143/// let key = dsa::read(WorkingKey::standing(info), &memory)?;
144/// assert_eq!(key.y().as_bytes(), [7]);
145/// assert!(key.parameters().is_none());
146/// # Ok::<(), structured_pkix::Error>(())
147/// ```
148pub fn read<'a, W: Work>(key: WorkingKey<'a>, execution: &W) -> Result<PublicKey<'a>> {
149 let info = key.key();
150 let own = info.algorithm();
151 if !same_oid(own.algorithm(), OID, execution, FIELD, own.offset())? {
152 return Err(Error::new(ErrorCode::UnexpectedField, FIELD, own.offset()));
153 }
154 // RFC 3279 §2.3.2: omission means no parameter element at all. Generic
155 // RFC5280 NULL inheritance must not repair an invalid DSA spelling.
156 if let Some(source) = own.parameters_nested()
157 && own.has_null_parameter()
158 {
159 let (_, written) = source.open(execution, PARAMETERS)?;
160 return Err(Error::new(
161 ErrorCode::MalformedValue,
162 PARAMETERS,
163 written.span().start,
164 ));
165 }
166 let parameters = if let Some(source) = key.parameter_source() {
167 let (reader, element) = source.open(execution, PARAMETERS)?;
168 if element.tag() != Tag::constructed(universal::SEQUENCE) {
169 return Err(Error::new(
170 ErrorCode::Encoding(structured_asn1::ErrorCode::UnexpectedTag),
171 PARAMETERS,
172 element.span().start,
173 ));
174 }
175 let mut fields = reader.enter(&element).field(PARAMETERS)?;
176 let p = component(&mut fields, PARAMETERS)?;
177 let q = component(&mut fields, PARAMETERS)?;
178 let g = component(&mut fields, PARAMETERS)?;
179 if !fields.is_empty() {
180 return Err(Error::new(
181 ErrorCode::TrailingData,
182 PARAMETERS,
183 fields.offset(),
184 ));
185 }
186 Some(Parameters {
187 element,
188 p,
189 q,
190 g,
191 inherited: own.parameters().is_none(),
192 })
193 } else {
194 None
195 };
196 let octets = info.whole_octets(FIELD)?;
197 let (reader, element) = own
198 .nested(octets, info.key_offset())
199 .open(execution, FIELD)?;
200 // RFC 3279 §2.3.2 requires DER for the INTEGER carried in the bits,
201 // independently of the enclosing source's BER permission.
202 let y = if reader.encoding().is_der() {
203 unsigned(&reader, element, FIELD)?
204 } else {
205 let mut strict = reader.reread(&element, Encoding::Der).field(FIELD)?;
206 component(&mut strict, FIELD)?
207 };
208 Ok(PublicKey { y, parameters })
209}
210
211fn component<'a>(reader: &mut ScopedReader<'a, '_>, field: &'static str) -> Result<Component<'a>> {
212 let element = reader
213 .expect(Tag::primitive(universal::INTEGER))
214 .field(field)?;
215 unsigned(reader, element, field)
216}
217
218fn unsigned<'a>(
219 reader: &ScopedReader<'a, '_>,
220 element: Element<'a>,
221 field: &'static str,
222) -> Result<Component<'a>> {
223 if element.tag() != Tag::primitive(universal::INTEGER) {
224 return Err(Error::new(
225 ErrorCode::Encoding(structured_asn1::ErrorCode::UnexpectedTag),
226 field,
227 element.span().start,
228 ));
229 }
230 let integer = reader.integer(&element).field(field)?;
231 if integer.is_negative() {
232 return Err(Error::new(
233 ErrorCode::MalformedValue,
234 field,
235 element.span().start,
236 ));
237 }
238 Ok(Component { element, integer })
239}