1mod error;
4
5pub use self::error::{Error, ErrorKind};
6
7use crate::{asymmetric, authentication, ecdh, ecdsa, hmac, opaque, otp, rsa, template, wrap};
8
9#[derive(Copy, Clone, Debug, Eq, PartialEq)]
11#[repr(u8)]
12pub enum Algorithm {
13 Asymmetric(asymmetric::Algorithm),
15
16 Authentication(authentication::Algorithm),
18
19 Ecdh(ecdh::Algorithm),
21
22 Ecdsa(ecdsa::Algorithm),
24
25 Hmac(hmac::Algorithm),
27
28 Mgf(rsa::mgf::Algorithm),
30
31 Opaque(opaque::Algorithm),
33
34 Rsa(rsa::Algorithm),
36
37 Template(template::Algorithm),
39
40 Wrap(wrap::Algorithm),
42
43 YubicoOtp(otp::Algorithm),
45}
46
47impl Algorithm {
48 pub fn from_u8(byte: u8) -> Result<Self, Error> {
50 Ok(match byte {
51 0x01..=0x08 | 0x19..=0x1c => Algorithm::Rsa(rsa::Algorithm::from_u8(byte)?),
52 0x09..=0x12 | 0x2e | 0x2f => {
53 Algorithm::Asymmetric(asymmetric::Algorithm::from_u8(byte)?)
54 }
55 0x13..=0x16 => Algorithm::Hmac(hmac::Algorithm::from_u8(byte)?),
56 0x17 | 0x2b..=0x2d => Algorithm::Ecdsa(ecdsa::Algorithm::from_u8(byte)?),
57 0x18 => Algorithm::Ecdh(ecdh::Algorithm::from_u8(byte)?),
58 0x1d | 0x29 | 0x2a => Algorithm::Wrap(wrap::Algorithm::from_u8(byte)?),
59 0x1e | 0x1f => Algorithm::Opaque(opaque::Algorithm::from_u8(byte)?),
60 0x20..=0x23 => Algorithm::Mgf(rsa::mgf::Algorithm::from_u8(byte)?),
61 0x24 => Algorithm::Template(template::Algorithm::from_u8(byte)?),
62 0x25 | 0x27 | 0x28 => Algorithm::YubicoOtp(otp::Algorithm::from_u8(byte)?),
63 0x26 => Algorithm::Authentication(authentication::Algorithm::from_u8(byte)?),
64 _ => fail!(
65 ErrorKind::TagInvalid,
66 "unknown algorithm ID: 0x{:02x}",
67 byte
68 ),
69 })
70 }
71
72 pub fn to_u8(self) -> u8 {
74 match self {
75 Algorithm::Asymmetric(alg) => alg.to_u8(),
76 Algorithm::Authentication(alg) => alg.to_u8(),
77 Algorithm::Ecdh(alg) => alg.to_u8(),
78 Algorithm::Ecdsa(alg) => alg.to_u8(),
79 Algorithm::Hmac(alg) => alg.to_u8(),
80 Algorithm::Mgf(alg) => alg.to_u8(),
81 Algorithm::Opaque(alg) => alg.to_u8(),
82 Algorithm::YubicoOtp(alg) => alg.to_u8(),
83 Algorithm::Rsa(alg) => alg.to_u8(),
84 Algorithm::Template(alg) => alg.to_u8(),
85 Algorithm::Wrap(alg) => alg.to_u8(),
86 }
87 }
88
89 pub fn asymmetric(self) -> Option<asymmetric::Algorithm> {
91 match self {
92 Algorithm::Asymmetric(alg) => Some(alg),
93 _ => None,
94 }
95 }
96
97 pub fn authentication(self) -> Option<authentication::Algorithm> {
99 match self {
100 Algorithm::Authentication(alg) => Some(alg),
101 _ => None,
102 }
103 }
104
105 pub fn ecdh(self) -> Option<ecdh::Algorithm> {
107 match self {
108 Algorithm::Ecdh(alg) => Some(alg),
109 _ => None,
110 }
111 }
112
113 pub fn ecdsa(self) -> Option<ecdsa::Algorithm> {
115 match self {
116 Algorithm::Ecdsa(alg) => Some(alg),
117 _ => None,
118 }
119 }
120
121 pub fn hmac(self) -> Option<hmac::Algorithm> {
123 match self {
124 Algorithm::Hmac(alg) => Some(alg),
125 _ => None,
126 }
127 }
128
129 pub fn mgf(self) -> Option<rsa::mgf::Algorithm> {
131 match self {
132 Algorithm::Mgf(alg) => Some(alg),
133 _ => None,
134 }
135 }
136
137 pub fn opaque(self) -> Option<opaque::Algorithm> {
139 match self {
140 Algorithm::Opaque(alg) => Some(alg),
141 _ => None,
142 }
143 }
144
145 pub fn otp(self) -> Option<otp::Algorithm> {
147 match self {
148 Algorithm::YubicoOtp(alg) => Some(alg),
149 _ => None,
150 }
151 }
152
153 pub fn rsa(self) -> Option<rsa::Algorithm> {
155 match self {
156 Algorithm::Rsa(alg) => Some(alg),
157 _ => None,
158 }
159 }
160
161 pub fn template(self) -> Option<template::Algorithm> {
163 match self {
164 Algorithm::Template(alg) => Some(alg),
165 _ => None,
166 }
167 }
168
169 pub fn wrap(self) -> Option<wrap::Algorithm> {
171 match self {
172 Algorithm::Wrap(alg) => Some(alg),
173 _ => None,
174 }
175 }
176}
177
178impl_algorithm_serializers!(Algorithm);
179
180impl From<asymmetric::Algorithm> for Algorithm {
181 fn from(alg: asymmetric::Algorithm) -> Algorithm {
182 Algorithm::Asymmetric(alg)
183 }
184}
185
186impl From<authentication::Algorithm> for Algorithm {
187 fn from(alg: authentication::Algorithm) -> Algorithm {
188 crate::Algorithm::Authentication(alg)
189 }
190}
191
192impl From<ecdh::Algorithm> for Algorithm {
193 fn from(alg: ecdh::Algorithm) -> Algorithm {
194 Algorithm::Ecdh(alg)
195 }
196}
197
198impl From<ecdsa::Algorithm> for Algorithm {
199 fn from(alg: ecdsa::Algorithm) -> Algorithm {
200 Algorithm::Ecdsa(alg)
201 }
202}
203
204impl From<hmac::Algorithm> for Algorithm {
205 fn from(alg: hmac::Algorithm) -> Algorithm {
206 Algorithm::Hmac(alg)
207 }
208}
209
210impl From<opaque::Algorithm> for Algorithm {
211 fn from(alg: opaque::Algorithm) -> Algorithm {
212 Algorithm::Opaque(alg)
213 }
214}
215
216impl From<otp::Algorithm> for Algorithm {
217 fn from(alg: otp::Algorithm) -> Algorithm {
218 Algorithm::YubicoOtp(alg)
219 }
220}
221
222impl From<rsa::Algorithm> for Algorithm {
223 fn from(alg: rsa::Algorithm) -> Algorithm {
224 Algorithm::Rsa(alg)
225 }
226}
227
228impl From<rsa::mgf::Algorithm> for Algorithm {
229 fn from(alg: rsa::mgf::Algorithm) -> Algorithm {
230 Algorithm::Mgf(alg)
231 }
232}
233
234impl From<template::Algorithm> for Algorithm {
235 fn from(alg: template::Algorithm) -> Algorithm {
236 Algorithm::Template(alg)
237 }
238}
239
240impl From<wrap::Algorithm> for Algorithm {
241 fn from(alg: wrap::Algorithm) -> Algorithm {
242 Algorithm::Wrap(alg)
243 }
244}
245
246#[cfg(test)]
247mod tests {
248 use super::*;
249
250 const ALGORITHM_MAPPING: &[(u8, Algorithm)] = &[
251 (
252 0x01,
253 Algorithm::Rsa(rsa::Algorithm::Pkcs1(rsa::pkcs1::Algorithm::Sha1)),
254 ),
255 (
256 0x02,
257 Algorithm::Rsa(rsa::Algorithm::Pkcs1(rsa::pkcs1::Algorithm::Sha256)),
258 ),
259 (
260 0x03,
261 Algorithm::Rsa(rsa::Algorithm::Pkcs1(rsa::pkcs1::Algorithm::Sha384)),
262 ),
263 (
264 0x04,
265 Algorithm::Rsa(rsa::Algorithm::Pkcs1(rsa::pkcs1::Algorithm::Sha512)),
266 ),
267 (
268 0x05,
269 Algorithm::Rsa(rsa::Algorithm::Pss(rsa::pss::Algorithm::Sha1)),
270 ),
271 (
272 0x06,
273 Algorithm::Rsa(rsa::Algorithm::Pss(rsa::pss::Algorithm::Sha256)),
274 ),
275 (
276 0x07,
277 Algorithm::Rsa(rsa::Algorithm::Pss(rsa::pss::Algorithm::Sha384)),
278 ),
279 (
280 0x08,
281 Algorithm::Rsa(rsa::Algorithm::Pss(rsa::pss::Algorithm::Sha512)),
282 ),
283 (0x09, Algorithm::Asymmetric(asymmetric::Algorithm::Rsa2048)),
284 (0x0a, Algorithm::Asymmetric(asymmetric::Algorithm::Rsa3072)),
285 (0x0b, Algorithm::Asymmetric(asymmetric::Algorithm::Rsa4096)),
286 (0x0c, Algorithm::Asymmetric(asymmetric::Algorithm::EcP256)),
287 (0x0d, Algorithm::Asymmetric(asymmetric::Algorithm::EcP384)),
288 (0x0e, Algorithm::Asymmetric(asymmetric::Algorithm::EcP521)),
289 (0x0f, Algorithm::Asymmetric(asymmetric::Algorithm::EcK256)),
290 (0x10, Algorithm::Asymmetric(asymmetric::Algorithm::EcBp256)),
291 (0x11, Algorithm::Asymmetric(asymmetric::Algorithm::EcBp384)),
292 (0x12, Algorithm::Asymmetric(asymmetric::Algorithm::EcBp512)),
293 (0x13, Algorithm::Hmac(hmac::Algorithm::Sha1)),
294 (0x14, Algorithm::Hmac(hmac::Algorithm::Sha256)),
295 (0x15, Algorithm::Hmac(hmac::Algorithm::Sha384)),
296 (0x16, Algorithm::Hmac(hmac::Algorithm::Sha512)),
297 (0x17, Algorithm::Ecdsa(ecdsa::Algorithm::Sha1)),
298 (0x18, Algorithm::Ecdh(ecdh::Algorithm::Ecdh)),
299 (
300 0x19,
301 Algorithm::Rsa(rsa::Algorithm::Oaep(rsa::oaep::Algorithm::Sha1)),
302 ),
303 (
304 0x1a,
305 Algorithm::Rsa(rsa::Algorithm::Oaep(rsa::oaep::Algorithm::Sha256)),
306 ),
307 (
308 0x1b,
309 Algorithm::Rsa(rsa::Algorithm::Oaep(rsa::oaep::Algorithm::Sha384)),
310 ),
311 (
312 0x1c,
313 Algorithm::Rsa(rsa::Algorithm::Oaep(rsa::oaep::Algorithm::Sha512)),
314 ),
315 (0x1d, Algorithm::Wrap(wrap::Algorithm::Aes128Ccm)),
316 (0x1e, Algorithm::Opaque(opaque::Algorithm::Data)),
317 (0x1f, Algorithm::Opaque(opaque::Algorithm::X509Certificate)),
318 (0x20, Algorithm::Mgf(rsa::mgf::Algorithm::Sha1)),
319 (0x21, Algorithm::Mgf(rsa::mgf::Algorithm::Sha256)),
320 (0x22, Algorithm::Mgf(rsa::mgf::Algorithm::Sha384)),
321 (0x23, Algorithm::Mgf(rsa::mgf::Algorithm::Sha512)),
322 (0x24, Algorithm::Template(template::Algorithm::Ssh)),
323 (0x25, Algorithm::YubicoOtp(otp::Algorithm::Aes128)),
324 (
325 0x26,
326 Algorithm::Authentication(authentication::Algorithm::YubicoAes),
327 ),
328 (0x27, Algorithm::YubicoOtp(otp::Algorithm::Aes192)),
329 (0x28, Algorithm::YubicoOtp(otp::Algorithm::Aes256)),
330 (0x29, Algorithm::Wrap(wrap::Algorithm::Aes192Ccm)),
331 (0x2a, Algorithm::Wrap(wrap::Algorithm::Aes256Ccm)),
332 (0x2b, Algorithm::Ecdsa(ecdsa::Algorithm::Sha256)),
333 (0x2c, Algorithm::Ecdsa(ecdsa::Algorithm::Sha384)),
334 (0x2d, Algorithm::Ecdsa(ecdsa::Algorithm::Sha512)),
335 (0x2e, Algorithm::Asymmetric(asymmetric::Algorithm::Ed25519)),
336 (0x2f, Algorithm::Asymmetric(asymmetric::Algorithm::EcP224)),
337 ];
338
339 #[test]
340 fn test_from_u8() {
341 for (tag, alg) in ALGORITHM_MAPPING {
342 assert_eq!(*alg, Algorithm::from_u8(*tag).unwrap());
343 }
344 }
345
346 #[test]
347 fn test_to_u8() {
348 for (tag, alg) in ALGORITHM_MAPPING {
349 assert_eq!(*tag, alg.to_u8());
350 }
351 }
352}