]> git.proxmox.com Git - rustc.git/blob - vendor/spki/src/algorithm.rs
New upstream version 1.71.1+dfsg1
[rustc.git] / vendor / spki / src / algorithm.rs
1 //! X.509 `AlgorithmIdentifier`
2
3 use crate::{Error, Result};
4 use core::cmp::Ordering;
5 use der::{
6 asn1::{AnyRef, Choice, ObjectIdentifier},
7 Decode, DecodeValue, DerOrd, Encode, EncodeValue, Header, Length, Reader, Sequence, ValueOrd,
8 Writer,
9 };
10
11 #[cfg(feature = "alloc")]
12 use der::asn1::Any;
13
14 /// X.509 `AlgorithmIdentifier` as defined in [RFC 5280 Section 4.1.1.2].
15 ///
16 /// ```text
17 /// AlgorithmIdentifier ::= SEQUENCE {
18 /// algorithm OBJECT IDENTIFIER,
19 /// parameters ANY DEFINED BY algorithm OPTIONAL }
20 /// ```
21 ///
22 /// [RFC 5280 Section 4.1.1.2]: https://tools.ietf.org/html/rfc5280#section-4.1.1.2
23 #[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
24 #[derive(Copy, Clone, Debug, Eq, PartialEq, PartialOrd, Ord)]
25 pub struct AlgorithmIdentifier<Params> {
26 /// Algorithm OID, i.e. the `algorithm` field in the `AlgorithmIdentifier`
27 /// ASN.1 schema.
28 pub oid: ObjectIdentifier,
29
30 /// Algorithm `parameters`.
31 pub parameters: Option<Params>,
32 }
33
34 impl<'a, Params> DecodeValue<'a> for AlgorithmIdentifier<Params>
35 where
36 Params: Choice<'a>,
37 {
38 fn decode_value<R: Reader<'a>>(reader: &mut R, header: Header) -> der::Result<Self> {
39 reader.read_nested(header.length, |reader| {
40 Ok(Self {
41 oid: reader.decode()?,
42 parameters: reader.decode()?,
43 })
44 })
45 }
46 }
47
48 impl<Params> EncodeValue for AlgorithmIdentifier<Params>
49 where
50 Params: Encode,
51 {
52 fn value_len(&self) -> der::Result<Length> {
53 self.oid.encoded_len()? + self.parameters.encoded_len()?
54 }
55
56 fn encode_value(&self, writer: &mut impl Writer) -> der::Result<()> {
57 self.oid.encode(writer)?;
58 self.parameters.encode(writer)?;
59 Ok(())
60 }
61 }
62
63 impl<'a, Params> Sequence<'a> for AlgorithmIdentifier<Params> where Params: Choice<'a> + Encode {}
64
65 impl<'a, Params> TryFrom<&'a [u8]> for AlgorithmIdentifier<Params>
66 where
67 Params: Choice<'a> + Encode,
68 {
69 type Error = Error;
70
71 fn try_from(bytes: &'a [u8]) -> Result<Self> {
72 Ok(Self::from_der(bytes)?)
73 }
74 }
75
76 impl<Params> ValueOrd for AlgorithmIdentifier<Params>
77 where
78 Params: DerOrd,
79 {
80 fn value_cmp(&self, other: &Self) -> der::Result<Ordering> {
81 match self.oid.der_cmp(&other.oid)? {
82 Ordering::Equal => self.parameters.der_cmp(&other.parameters),
83 other => Ok(other),
84 }
85 }
86 }
87
88 /// `AlgorithmIdentifier` reference which has `AnyRef` parameters.
89 pub type AlgorithmIdentifierRef<'a> = AlgorithmIdentifier<AnyRef<'a>>;
90
91 /// `AlgorithmIdentifier` reference which has `Any` parameters.
92 #[cfg(feature = "alloc")]
93 pub type AlgorithmIdentifierOwned = AlgorithmIdentifier<Any>;
94
95 impl<Params> AlgorithmIdentifier<Params> {
96 /// Assert the `algorithm` OID is an expected value.
97 pub fn assert_algorithm_oid(&self, expected_oid: ObjectIdentifier) -> Result<ObjectIdentifier> {
98 if self.oid == expected_oid {
99 Ok(expected_oid)
100 } else {
101 Err(Error::OidUnknown { oid: expected_oid })
102 }
103 }
104 }
105
106 impl<'a> AlgorithmIdentifierRef<'a> {
107 /// Assert `parameters` is an OID and has the expected value.
108 pub fn assert_parameters_oid(
109 &self,
110 expected_oid: ObjectIdentifier,
111 ) -> Result<ObjectIdentifier> {
112 let actual_oid = self.parameters_oid()?;
113
114 if actual_oid == expected_oid {
115 Ok(actual_oid)
116 } else {
117 Err(Error::OidUnknown { oid: expected_oid })
118 }
119 }
120
121 /// Assert the values of the `algorithm` and `parameters` OIDs.
122 pub fn assert_oids(
123 &self,
124 algorithm: ObjectIdentifier,
125 parameters: ObjectIdentifier,
126 ) -> Result<()> {
127 self.assert_algorithm_oid(algorithm)?;
128 self.assert_parameters_oid(parameters)?;
129 Ok(())
130 }
131
132 /// Get the `parameters` field as an [`AnyRef`].
133 ///
134 /// Returns an error if `parameters` are `None`.
135 pub fn parameters_any(&self) -> Result<AnyRef<'a>> {
136 self.parameters.ok_or(Error::AlgorithmParametersMissing)
137 }
138
139 /// Get the `parameters` field as an [`ObjectIdentifier`].
140 ///
141 /// Returns an error if it is absent or not an OID.
142 pub fn parameters_oid(&self) -> Result<ObjectIdentifier> {
143 Ok(ObjectIdentifier::try_from(self.parameters_any()?)?)
144 }
145
146 /// Convert to a pair of [`ObjectIdentifier`]s.
147 ///
148 /// This method is helpful for decomposing in match statements. Note in
149 /// particular that `NULL` parameters are treated the same as missing
150 /// parameters.
151 ///
152 /// Returns an error if parameters are present but not an OID.
153 pub fn oids(&self) -> der::Result<(ObjectIdentifier, Option<ObjectIdentifier>)> {
154 Ok((
155 self.oid,
156 match self.parameters {
157 None => None,
158 Some(p) => match p {
159 AnyRef::NULL => None,
160 _ => Some(p.decode_as::<ObjectIdentifier>()?),
161 },
162 },
163 ))
164 }
165 }
166
167 #[cfg(feature = "alloc")]
168 mod allocating {
169 use super::*;
170 use der::referenced::*;
171
172 impl<'a> RefToOwned<'a> for AlgorithmIdentifierRef<'a> {
173 type Owned = AlgorithmIdentifierOwned;
174 fn ref_to_owned(&self) -> Self::Owned {
175 AlgorithmIdentifier {
176 oid: self.oid,
177 parameters: self.parameters.ref_to_owned(),
178 }
179 }
180 }
181
182 impl OwnedToRef for AlgorithmIdentifierOwned {
183 type Borrowed<'a> = AlgorithmIdentifierRef<'a>;
184 fn owned_to_ref(&self) -> Self::Borrowed<'_> {
185 AlgorithmIdentifier {
186 oid: self.oid,
187 parameters: self.parameters.owned_to_ref(),
188 }
189 }
190 }
191 }