oath_authenticator/
oath.rs

1use core::convert::TryFrom;
2
3use serde::{Deserialize, Serialize};
4
5
6pub const HMAC_MINIMUM_KEY_SIZE: usize = 14;
7
8#[repr(u8)]
9#[derive(Clone, Copy, Debug, Eq, PartialEq)]
10pub enum Tag {
11    Name = 0x71,
12    NameList = 0x72,
13    Key = 0x73,
14    Challenge = 0x74,
15    Response = 0x75,
16    /// Tag denots what follows is (digits, dynamically truncated HMAC digest)
17    ///
18    /// The client then further processes u32::from_be_bytes(truncated-digest)/10**digits.
19    TruncatedResponse = 0x76,
20    Hotp = 0x77,
21    Property = 0x78,
22    Version = 0x79,
23    InitialMovingFactor = 0x7a,
24    Algorithm = 0x7b,
25    Touch = 0x7c,
26}
27
28#[repr(u8)]
29#[derive(Clone, Copy, Debug, Deserialize, Eq, PartialEq, Serialize)]
30pub enum Algorithm {
31    Sha1 = 0x01,
32    Sha256 = 0x02,
33    Sha512 = 0x03,
34}
35
36impl TryFrom<u8> for Algorithm {
37    type Error = iso7816::Status;
38    fn try_from(byte: u8) -> Result<Self, Self::Error> {
39        use Algorithm::*;
40        Ok(match byte & 0x0f {
41            0x1 => Sha1,
42            0x2 => Sha256,
43            0x3 => Sha512,
44            _ => return Err(Self::Error::IncorrectDataParameter),
45        })
46    }
47}
48
49#[repr(u8)]
50#[derive(Clone, Copy, Debug, Deserialize, Eq, PartialEq, Serialize)]
51pub enum Kind {
52    Hotp = 0x10,
53    Totp = 0x20,
54}
55
56impl TryFrom<u8> for Kind {
57    type Error = iso7816::Status;
58    fn try_from(byte: u8) -> Result<Self, Self::Error> {
59        Ok(match byte & 0xf0 {
60            0x10 => Kind::Hotp,
61            0x20 => Kind::Totp,
62            _ => return Err(Self::Error::IncorrectDataParameter),
63        })
64    }
65}
66
67pub fn combine(kind: Kind, algorithm: Algorithm) -> u8 {
68    kind as u8 | algorithm as u8
69}
70
71#[repr(u8)]
72#[derive(Clone, Copy, Debug, Eq, PartialEq)]
73pub enum Properties {
74    RequireTouch = 0x02,
75}
76
77#[repr(u8)]
78#[derive(Clone, Copy, Debug, Eq, PartialEq)]
79pub enum Instruction {
80    Put = 0x01,
81    Delete = 0x02,
82    SetCode = 0x03,
83    Reset = 0x04,
84    List = 0xa1,
85    Calculate = 0xa2,
86    Validate = 0xa3,
87    CalculateAll = 0xa4,
88    SendRemaining = 0xa5,
89}
90
91impl TryFrom<u8> for Instruction {
92    type Error = iso7816::Status;
93    fn try_from(byte: u8) -> Result<Self, Self::Error> {
94        use Instruction::*;
95        Ok(match byte {
96            0x01 => Put,
97            0x02 => Delete,
98            0x03 => SetCode,
99            0x04 => Reset,
100            0xa1 => List,
101            0xa2 => Calculate,
102            0xa3 => Validate,
103            0xa4 => CalculateAll,
104            0xa5 => SendRemaining,
105            _ => return Err(Self::Error::InstructionNotSupportedOrInvalid),
106        })
107    }
108}
109
110impl PartialEq<u8> for Instruction {
111    fn eq(&self, other: &u8) -> bool {
112        *self as u8 == *other
113    }
114}
115
116// class MASK(IntEnum):
117//     ALGO = 0x0f
118//     TYPE = 0xf0