1use crate::AlgorithmIdentifierRef;
6use der::{
7 Decode, DecodeValue, Encode, EncodeValue, ErrorKind, Length, Reader, Sequence, Tag, Writer,
8 asn1::{AnyRef, ObjectIdentifier, OctetStringRef},
9};
10
11pub const PBE_WITH_MD2_AND_DES_CBC_OID: ObjectIdentifier =
13 ObjectIdentifier::new_unwrap("1.2.840.113549.1.5.1");
14
15pub const PBE_WITH_MD2_AND_RC2_CBC_OID: ObjectIdentifier =
17 ObjectIdentifier::new_unwrap("1.2.840.113549.1.5.4");
18
19pub const PBE_WITH_MD5_AND_DES_CBC_OID: ObjectIdentifier =
21 ObjectIdentifier::new_unwrap("1.2.840.113549.1.5.3");
22
23pub const PBE_WITH_MD5_AND_RC2_CBC_OID: ObjectIdentifier =
25 ObjectIdentifier::new_unwrap("1.2.840.113549.1.5.6");
26
27pub const PBE_WITH_SHA1_AND_DES_CBC_OID: ObjectIdentifier =
29 ObjectIdentifier::new_unwrap("1.2.840.113549.1.5.10");
30
31pub const PBE_WITH_SHA1_AND_RC2_CBC_OID: ObjectIdentifier =
33 ObjectIdentifier::new_unwrap("1.2.840.113549.1.5.11");
34
35pub const SALT_LENGTH: usize = 8;
37
38#[derive(Clone, Copy, Debug, Eq, PartialEq)]
54pub struct Algorithm {
55 pub encryption: EncryptionScheme,
57
58 pub parameters: Parameters,
60}
61
62impl Algorithm {
63 #[must_use]
65 pub fn oid(&self) -> ObjectIdentifier {
66 self.encryption.oid()
67 }
68}
69
70impl<'a> DecodeValue<'a> for Algorithm {
71 type Error = der::Error;
72
73 fn decode_value<R: Reader<'a>>(reader: &mut R, header: der::Header) -> der::Result<Self> {
74 AlgorithmIdentifierRef::decode_value(reader, header)?.try_into()
75 }
76}
77
78impl EncodeValue for Algorithm {
79 fn value_len(&self) -> der::Result<Length> {
80 self.encryption.encoded_len()? + self.parameters.encoded_len()?
81 }
82
83 fn encode_value(&self, writer: &mut impl Writer) -> der::Result<()> {
84 self.encryption.encode(writer)?;
85 self.parameters.encode(writer)?;
86 Ok(())
87 }
88}
89
90impl Sequence<'_> for Algorithm {}
91
92impl<'a> TryFrom<AlgorithmIdentifierRef<'a>> for Algorithm {
93 type Error = der::Error;
94
95 fn try_from(alg: AlgorithmIdentifierRef<'a>) -> der::Result<Self> {
96 let encryption =
98 EncryptionScheme::try_from(alg.oid).map_err(|_| Tag::ObjectIdentifier.value_error())?;
99
100 let parameters = alg
101 .parameters
102 .ok_or_else(|| Tag::OctetString.value_error())?
103 .try_into()?;
104
105 Ok(Self {
106 encryption,
107 parameters,
108 })
109 }
110}
111
112#[derive(Clone, Copy, Debug, Eq, PartialEq)]
122pub struct Parameters {
123 pub salt: [u8; SALT_LENGTH],
125
126 pub iteration_count: u16,
128}
129
130impl<'a> DecodeValue<'a> for Parameters {
131 type Error = der::Error;
132
133 fn decode_value<R: Reader<'a>>(reader: &mut R, header: der::Header) -> der::Result<Self> {
134 AnyRef::decode_value(reader, header)?.try_into()
135 }
136}
137
138impl EncodeValue for Parameters {
139 fn value_len(&self) -> der::Result<Length> {
140 OctetStringRef::new(&self.salt)?.encoded_len()? + self.iteration_count.encoded_len()?
141 }
142
143 fn encode_value(&self, writer: &mut impl Writer) -> der::Result<()> {
144 OctetStringRef::new(&self.salt)?.encode(writer)?;
145 self.iteration_count.encode(writer)?;
146 Ok(())
147 }
148}
149
150impl Sequence<'_> for Parameters {}
151
152impl TryFrom<AnyRef<'_>> for Parameters {
153 type Error = der::Error;
154
155 fn try_from(any: AnyRef<'_>) -> der::Result<Parameters> {
156 any.sequence(|reader| {
157 Ok(Parameters {
158 salt: <&OctetStringRef>::decode(reader)?
159 .as_bytes()
160 .try_into()
161 .map_err(|_| Tag::OctetString.value_error())?,
162 iteration_count: reader.decode()?,
163 })
164 })
165 }
166}
167
168#[derive(Copy, Clone, Debug, Eq, PartialEq)]
172pub enum EncryptionScheme {
173 PbeWithMd2AndDesCbc,
175
176 PbeWithMd2AndRc2Cbc,
178
179 PbeWithMd5AndDesCbc,
181
182 PbeWithMd5AndRc2Cbc,
184
185 PbeWithSha1AndDesCbc,
187
188 PbeWithSha1AndRc2Cbc,
190}
191
192impl TryFrom<ObjectIdentifier> for EncryptionScheme {
193 type Error = der::Error;
194
195 fn try_from(oid: ObjectIdentifier) -> der::Result<Self> {
196 match oid {
197 PBE_WITH_MD2_AND_DES_CBC_OID => Ok(Self::PbeWithMd2AndDesCbc),
198 PBE_WITH_MD2_AND_RC2_CBC_OID => Ok(Self::PbeWithMd2AndRc2Cbc),
199 PBE_WITH_MD5_AND_DES_CBC_OID => Ok(Self::PbeWithMd5AndDesCbc),
200 PBE_WITH_MD5_AND_RC2_CBC_OID => Ok(Self::PbeWithMd5AndRc2Cbc),
201 PBE_WITH_SHA1_AND_DES_CBC_OID => Ok(Self::PbeWithSha1AndDesCbc),
202 PBE_WITH_SHA1_AND_RC2_CBC_OID => Ok(Self::PbeWithSha1AndRc2Cbc),
203 _ => Err(ErrorKind::OidUnknown { oid }.into()),
204 }
205 }
206}
207
208impl EncryptionScheme {
209 #[must_use]
211 pub fn cipher(self) -> SymmetricCipher {
212 match self {
213 Self::PbeWithMd2AndDesCbc => SymmetricCipher::DesCbc,
214 Self::PbeWithMd2AndRc2Cbc => SymmetricCipher::Rc2Cbc,
215 Self::PbeWithMd5AndDesCbc => SymmetricCipher::DesCbc,
216 Self::PbeWithMd5AndRc2Cbc => SymmetricCipher::Rc2Cbc,
217 Self::PbeWithSha1AndDesCbc => SymmetricCipher::DesCbc,
218 Self::PbeWithSha1AndRc2Cbc => SymmetricCipher::Rc2Cbc,
219 }
220 }
221
222 #[must_use]
224 pub fn digest(self) -> DigestAlgorithm {
225 match self {
226 Self::PbeWithMd2AndDesCbc => DigestAlgorithm::Md2,
227 Self::PbeWithMd2AndRc2Cbc => DigestAlgorithm::Md2,
228 Self::PbeWithMd5AndDesCbc => DigestAlgorithm::Md5,
229 Self::PbeWithMd5AndRc2Cbc => DigestAlgorithm::Md5,
230 Self::PbeWithSha1AndDesCbc => DigestAlgorithm::Sha1,
231 Self::PbeWithSha1AndRc2Cbc => DigestAlgorithm::Sha1,
232 }
233 }
234
235 #[must_use]
237 pub fn oid(self) -> ObjectIdentifier {
238 match self {
239 Self::PbeWithMd2AndDesCbc => PBE_WITH_MD2_AND_DES_CBC_OID,
240 Self::PbeWithMd2AndRc2Cbc => PBE_WITH_MD2_AND_RC2_CBC_OID,
241 Self::PbeWithMd5AndDesCbc => PBE_WITH_MD5_AND_DES_CBC_OID,
242 Self::PbeWithMd5AndRc2Cbc => PBE_WITH_MD5_AND_RC2_CBC_OID,
243 Self::PbeWithSha1AndDesCbc => PBE_WITH_SHA1_AND_DES_CBC_OID,
244 Self::PbeWithSha1AndRc2Cbc => PBE_WITH_SHA1_AND_RC2_CBC_OID,
245 }
246 }
247}
248
249impl Encode for EncryptionScheme {
250 fn encoded_len(&self) -> der::Result<Length> {
251 self.oid().encoded_len()
252 }
253
254 fn encode(&self, writer: &mut impl Writer) -> der::Result<()> {
255 self.oid().encode(writer)
256 }
257}
258
259#[derive(Copy, Clone, Debug, Eq, PartialEq)]
261pub enum DigestAlgorithm {
262 Md2,
264
265 Md5,
267
268 Sha1,
270}
271
272#[derive(Copy, Clone, Debug, Eq, PartialEq)]
274pub enum SymmetricCipher {
275 DesCbc,
277
278 Rc2Cbc,
280}