spki/
algorithm.rs
1use crate::{Error, Result};
4use core::cmp::Ordering;
5use 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")]
12use der::asn1::Any;
13
14#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
24#[derive(Copy, Clone, Debug, Eq, PartialEq, PartialOrd, Ord)]
25pub struct AlgorithmIdentifier<Params> {
26 pub oid: ObjectIdentifier,
29
30 pub parameters: Option<Params>,
32}
33
34impl<'a, Params> DecodeValue<'a> for AlgorithmIdentifier<Params>
35where
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
48impl<Params> EncodeValue for AlgorithmIdentifier<Params>
49where
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
63impl<'a, Params> Sequence<'a> for AlgorithmIdentifier<Params> where Params: Choice<'a> + Encode {}
64
65impl<'a, Params> TryFrom<&'a [u8]> for AlgorithmIdentifier<Params>
66where
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
76impl<Params> ValueOrd for AlgorithmIdentifier<Params>
77where
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
88pub type AlgorithmIdentifierRef<'a> = AlgorithmIdentifier<AnyRef<'a>>;
90
91pub type AlgorithmIdentifierWithOid = AlgorithmIdentifier<ObjectIdentifier>;
93
94#[cfg(feature = "alloc")]
96pub type AlgorithmIdentifierOwned = AlgorithmIdentifier<Any>;
97
98impl<Params> AlgorithmIdentifier<Params> {
99 pub fn assert_algorithm_oid(&self, expected_oid: ObjectIdentifier) -> Result<ObjectIdentifier> {
101 if self.oid == expected_oid {
102 Ok(expected_oid)
103 } else {
104 Err(Error::OidUnknown { oid: expected_oid })
105 }
106 }
107}
108
109impl<'a> AlgorithmIdentifierRef<'a> {
110 pub fn assert_parameters_oid(
112 &self,
113 expected_oid: ObjectIdentifier,
114 ) -> Result<ObjectIdentifier> {
115 let actual_oid = self.parameters_oid()?;
116
117 if actual_oid == expected_oid {
118 Ok(actual_oid)
119 } else {
120 Err(Error::OidUnknown { oid: expected_oid })
121 }
122 }
123
124 pub fn assert_oids(
126 &self,
127 algorithm: ObjectIdentifier,
128 parameters: ObjectIdentifier,
129 ) -> Result<()> {
130 self.assert_algorithm_oid(algorithm)?;
131 self.assert_parameters_oid(parameters)?;
132 Ok(())
133 }
134
135 pub fn parameters_any(&self) -> Result<AnyRef<'a>> {
139 self.parameters.ok_or(Error::AlgorithmParametersMissing)
140 }
141
142 pub fn parameters_oid(&self) -> Result<ObjectIdentifier> {
146 Ok(ObjectIdentifier::try_from(self.parameters_any()?)?)
147 }
148
149 pub fn oids(&self) -> der::Result<(ObjectIdentifier, Option<ObjectIdentifier>)> {
157 Ok((
158 self.oid,
159 match self.parameters {
160 None => None,
161 Some(p) => match p {
162 AnyRef::NULL => None,
163 _ => Some(p.decode_as::<ObjectIdentifier>()?),
164 },
165 },
166 ))
167 }
168}
169
170#[cfg(feature = "alloc")]
171mod allocating {
172 use super::*;
173 use der::referenced::*;
174
175 impl<'a> RefToOwned<'a> for AlgorithmIdentifierRef<'a> {
176 type Owned = AlgorithmIdentifierOwned;
177 fn ref_to_owned(&self) -> Self::Owned {
178 AlgorithmIdentifier {
179 oid: self.oid,
180 parameters: self.parameters.ref_to_owned(),
181 }
182 }
183 }
184
185 impl OwnedToRef for AlgorithmIdentifierOwned {
186 type Borrowed<'a> = AlgorithmIdentifierRef<'a>;
187 fn owned_to_ref(&self) -> Self::Borrowed<'_> {
188 AlgorithmIdentifier {
189 oid: self.oid,
190 parameters: self.parameters.owned_to_ref(),
191 }
192 }
193 }
194}