yubihsm/
algorithm.rs

1//! Cryptographic algorithms supported by the YubiHSM 2
2
3mod error;
4
5pub use self::error::{Error, ErrorKind};
6
7use crate::{asymmetric, authentication, ecdh, ecdsa, hmac, opaque, otp, rsa, template, wrap};
8
9/// Cryptographic algorithm types supported by the `YubiHSM 2`
10#[derive(Copy, Clone, Debug, Eq, PartialEq)]
11#[repr(u8)]
12pub enum Algorithm {
13    /// Asymmetric algorithms
14    Asymmetric(asymmetric::Algorithm),
15
16    /// YubiHSM 2 symmetric PSK authentication
17    Authentication(authentication::Algorithm),
18
19    /// Elliptic Curve Diffie-Hellman (i.e. key exchange) algorithms
20    Ecdh(ecdh::Algorithm),
21
22    /// ECDSA algorithms
23    Ecdsa(ecdsa::Algorithm),
24
25    /// HMAC algorithms
26    Hmac(hmac::Algorithm),
27
28    /// RSA-PSS mask generating functions
29    Mgf(rsa::mgf::Algorithm),
30
31    /// Opaque data types
32    Opaque(opaque::Algorithm),
33
34    /// RSA algorithms (signing and encryption)
35    Rsa(rsa::Algorithm),
36
37    /// SSH template algorithms
38    Template(template::Algorithm),
39
40    /// Object wrap (i.e. HSM-to-HSM encryption) algorithms
41    Wrap(wrap::Algorithm),
42
43    /// Yubico OTP algorithms
44    YubicoOtp(otp::Algorithm),
45}
46
47impl Algorithm {
48    /// Convert an unsigned byte into an Algorithm (if valid)
49    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    /// Serialize algorithm ID as a byte
73    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    /// Get `asymmetric::Algorithm`
90    pub fn asymmetric(self) -> Option<asymmetric::Algorithm> {
91        match self {
92            Algorithm::Asymmetric(alg) => Some(alg),
93            _ => None,
94        }
95    }
96
97    /// Get `authentication::Algorithm`
98    pub fn authentication(self) -> Option<authentication::Algorithm> {
99        match self {
100            Algorithm::Authentication(alg) => Some(alg),
101            _ => None,
102        }
103    }
104
105    /// Get `ecdh::Algorithm`
106    pub fn ecdh(self) -> Option<ecdh::Algorithm> {
107        match self {
108            Algorithm::Ecdh(alg) => Some(alg),
109            _ => None,
110        }
111    }
112
113    /// Get `ecdsa::Algorithm`
114    pub fn ecdsa(self) -> Option<ecdsa::Algorithm> {
115        match self {
116            Algorithm::Ecdsa(alg) => Some(alg),
117            _ => None,
118        }
119    }
120
121    /// Get `hmac::Algorithm`
122    pub fn hmac(self) -> Option<hmac::Algorithm> {
123        match self {
124            Algorithm::Hmac(alg) => Some(alg),
125            _ => None,
126        }
127    }
128
129    /// Get `rsa::mgf::Algorithm`
130    pub fn mgf(self) -> Option<rsa::mgf::Algorithm> {
131        match self {
132            Algorithm::Mgf(alg) => Some(alg),
133            _ => None,
134        }
135    }
136
137    /// Get `opaque::Algorithm`
138    pub fn opaque(self) -> Option<opaque::Algorithm> {
139        match self {
140            Algorithm::Opaque(alg) => Some(alg),
141            _ => None,
142        }
143    }
144
145    /// Get `OtpAlg`
146    pub fn otp(self) -> Option<otp::Algorithm> {
147        match self {
148            Algorithm::YubicoOtp(alg) => Some(alg),
149            _ => None,
150        }
151    }
152
153    /// Get `rsa::Algorithm`
154    pub fn rsa(self) -> Option<rsa::Algorithm> {
155        match self {
156            Algorithm::Rsa(alg) => Some(alg),
157            _ => None,
158        }
159    }
160
161    /// Get `template::Algorithm`
162    pub fn template(self) -> Option<template::Algorithm> {
163        match self {
164            Algorithm::Template(alg) => Some(alg),
165            _ => None,
166        }
167    }
168
169    /// Get `wrap::Algorithm`
170    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}