ecc608_linux/
slot_config.rs

1use bitfield::bitfield;
2use bytes::Buf;
3use serde_derive::Serialize;
4
5bitfield! {
6    pub struct ReadKey(u8);
7    impl Debug;
8    pub external_signatures, set_external_signatures: 0;
9    pub internal_signatures, set_internal_signatures: 1;
10    pub ecdh_operation, set_ecdh_operation: 2;
11    pub ecdh_write_slot, set_ecdh_write_slot: 3;
12}
13
14impl From<u8> for ReadKey {
15    fn from(v: u8) -> Self {
16        Self(v)
17    }
18}
19
20impl From<ReadKey> for u8 {
21    fn from(v: ReadKey) -> Self {
22        v.0
23    }
24}
25
26impl Default for ReadKey {
27    fn default() -> Self {
28        let mut result = Self(0);
29        result.set_internal_signatures(true);
30        result.set_external_signatures(true);
31        result.set_ecdh_operation(true);
32        result
33    }
34}
35
36/// Write cofiguration from the write_config slot bits for a given command. The
37/// interpretation of the write_config bits differs based on the command used.
38#[derive(Serialize, Debug, PartialEq, Eq)]
39#[serde(rename_all = "lowercase")]
40pub enum WriteConfig {
41    Write(_WriteConfig),
42    DeriveKey(DeriveKeyConfig),
43    GenKey(GenKeyConfig),
44    PrivWrite(PrivWriteConfig),
45}
46
47#[derive(Debug, PartialEq, Eq)]
48pub enum WriteCommand {
49    Write,
50    DeriveKey,
51    GenKey,
52    PrivWrite,
53}
54
55impl WriteConfig {
56    pub fn from(cmd: WriteCommand, v: u8) -> Self {
57        match cmd {
58            WriteCommand::Write => Self::Write(v.into()),
59            WriteCommand::DeriveKey => Self::DeriveKey(v.into()),
60            WriteCommand::GenKey => Self::GenKey(v.into()),
61            WriteCommand::PrivWrite => Self::PrivWrite(v.into()),
62        }
63    }
64}
65
66impl From<WriteConfig> for u8 {
67    fn from(v: WriteConfig) -> Self {
68        match v {
69            WriteConfig::Write(cfg) => cfg.into(),
70            WriteConfig::DeriveKey(cfg) => cfg.into(),
71            WriteConfig::GenKey(cfg) => cfg.into(),
72            WriteConfig::PrivWrite(cfg) => cfg.into(),
73        }
74    }
75}
76
77impl Default for WriteConfig {
78    fn default() -> Self {
79        WriteConfig::GenKey(GenKeyConfig::Valid)
80    }
81}
82
83#[derive(Serialize, Debug, PartialEq, Eq)]
84#[serde(rename_all = "lowercase")]
85pub enum _WriteConfig {
86    /// Clear text writes are always permitted on this slot. Slots set to
87    /// alwaysshould never be used as key storage. Either 4 or 32 bytes may
88    /// bewritten to this slot
89    Always,
90    /// If a validated public key is stored in the slot, writes are prohibited.
91    /// UseVerify(Invalidate) to invalidate prior to writing. Do not use
92    /// thismode unless the slot contains a public key.
93    PubInValid,
94    /// Writes are never permitted on this slot using the Write command.Slots
95    /// set to never can still be used as key storage.
96    Never,
97    /// Writes to this slot require a properly computed MAC, and the inputdata
98    /// must be encrypted by the system with WriteKey using theencryption
99    /// algorithm documented in the Write command description(Section Write
100    /// Command). 4 byte writes to this slot are prohibited.
101    Encrypt,
102}
103
104impl From<u8> for _WriteConfig {
105    fn from(v: u8) -> Self {
106        match v {
107            0 => _WriteConfig::Always,
108            1 => _WriteConfig::PubInValid,
109            _ if v >> 1 == 1 => _WriteConfig::Never,
110            _ if v >> 2 == 2 => _WriteConfig::Never,
111            _ if v & 4 == 4 => _WriteConfig::Encrypt,
112            _ => panic!("invalid write config {:?}", v),
113        }
114    }
115}
116
117impl From<_WriteConfig> for u8 {
118    fn from(v: _WriteConfig) -> Self {
119        match v {
120            _WriteConfig::Always => 0,
121            _WriteConfig::PubInValid => 1,
122            _WriteConfig::Never => 2,
123            _WriteConfig::Encrypt => 4,
124        }
125    }
126}
127
128#[derive(Serialize, Debug, PartialEq, Eq)]
129#[serde(rename_all = "lowercase")]
130pub enum DeriveKeyConfig {
131    ///  DeriveKey command can be run with/without authorizing MAC. Source Key:
132    /// Target
133    Roll(bool),
134    /// DeriveKey command can be run with/without authorizing MAC. Source Key:
135    /// Parent
136    Create(bool),
137    /// Slots with this write configutation can not be used as the target of a
138    /// DeriveKey.
139    Invalid,
140}
141
142impl From<u8> for DeriveKeyConfig {
143    fn from(v: u8) -> Self {
144        match v & 11 {
145            2 => Self::Roll(false),
146            10 => Self::Roll(true),
147            3 => Self::Create(false),
148            11 => Self::Create(true),
149            _ => Self::Invalid,
150        }
151    }
152}
153
154impl From<DeriveKeyConfig> for u8 {
155    fn from(v: DeriveKeyConfig) -> Self {
156        match v {
157            DeriveKeyConfig::Roll(false) => 2,
158            DeriveKeyConfig::Roll(true) => 10,
159            DeriveKeyConfig::Create(false) => 3,
160            DeriveKeyConfig::Create(true) => 11,
161            DeriveKeyConfig::Invalid => 0,
162        }
163    }
164}
165
166#[derive(Serialize, Debug, PartialEq, Eq)]
167#[serde(rename_all = "lowercase")]
168pub enum GenKeyConfig {
169    /// GenKey may not be used to write random keys into this slot.
170    Valid,
171    /// GenKey may be used to write random keys into this slot.
172    Invalid,
173}
174
175impl From<u8> for GenKeyConfig {
176    fn from(v: u8) -> Self {
177        match v & 2 == 0 {
178            true => Self::Invalid,
179            _ => Self::Valid,
180        }
181    }
182}
183
184impl From<GenKeyConfig> for u8 {
185    fn from(v: GenKeyConfig) -> Self {
186        match v {
187            GenKeyConfig::Invalid => 0,
188            GenKeyConfig::Valid => 2,
189        }
190    }
191}
192
193#[derive(Serialize, Debug, PartialEq, Eq)]
194#[serde(rename_all = "lowercase")]
195pub enum PrivWriteConfig {
196    /// PrivWrite will return an error if the target key slot has this value.
197    Invalid,
198    /// Writes to this slot require a properly computed MAC and the inputdata
199    /// must be encrypted by the system with SlotConfig.WriteKey using the
200    /// encryption algorithm documented with PrivWrite.
201    Encrypt,
202}
203
204impl From<u8> for PrivWriteConfig {
205    fn from(v: u8) -> Self {
206        match v & 4 == 0 {
207            true => Self::Invalid,
208            _ => Self::Encrypt,
209        }
210    }
211}
212
213impl From<PrivWriteConfig> for u8 {
214    fn from(v: PrivWriteConfig) -> Self {
215        match v {
216            PrivWriteConfig::Invalid => 0,
217            PrivWriteConfig::Encrypt => 4,
218        }
219    }
220}
221
222bitfield! {
223    #[derive(PartialEq, Eq)]
224    pub struct SlotConfig(u16);
225    impl Debug;
226    pub secret, set_secret: 15;
227    pub encrypt_read, set_encrypt_read: 14;
228    pub limited_use, set_limited_use: 13;
229    pub no_mac, set_no_mac: 12;
230    pub u8, from into ReadKey, read_key, set_read_key: 11, 8;
231    u8, _write_config, _set_write_config: 7, 4;
232    pub u8, write_key, set_write_key: 3, 0;
233}
234
235impl From<&[u8]> for SlotConfig {
236    fn from(v: &[u8]) -> Self {
237        let mut buf = v;
238        Self(buf.get_u16())
239    }
240}
241
242impl From<u16> for SlotConfig {
243    fn from(v: u16) -> Self {
244        Self(v)
245    }
246}
247
248impl From<SlotConfig> for u16 {
249    fn from(v: SlotConfig) -> Self {
250        v.0
251    }
252}
253
254impl From<&SlotConfig> for u16 {
255    fn from(v: &SlotConfig) -> Self {
256        v.0
257    }
258}
259
260/// A convenience function to get a slot configuratoin set up to
261/// generate and store ECDSA private keys.
262impl Default for SlotConfig {
263    fn default() -> Self {
264        let mut result = SlotConfig(0);
265        result.set_write_config(WriteConfig::default());
266        result.set_write_key(0);
267        result.set_secret(true);
268        result.set_encrypt_read(false);
269        result.set_limited_use(false);
270        result.set_no_mac(true);
271        result.set_read_key(ReadKey::default());
272        result
273    }
274}
275
276impl SlotConfig {
277    pub fn write_config(&self, cmd: WriteCommand) -> WriteConfig {
278        WriteConfig::from(cmd, self._write_config())
279    }
280
281    pub fn set_write_config<C>(&mut self, config: C)
282    where
283        C: Into<u8>,
284    {
285        self._set_write_config(config.into())
286    }
287}
288
289impl serde::ser::Serialize for SlotConfig {
290    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
291    where
292        S: serde::ser::Serializer,
293    {
294        use serde::ser::SerializeStruct;
295        let mut state = serializer.serialize_struct("slot_config", 7)?;
296        state.serialize_field("secret", &self.secret())?;
297        state.serialize_field("encrypt_read", &self.encrypt_read())?;
298        state.serialize_field("limited_use", &self.limited_use())?;
299        state.serialize_field("no_mac", &self.no_mac())?;
300        state.serialize_field("read_key", &self.read_key())?;
301        state.serialize_field("write_config", &self._write_config())?;
302        state.serialize_field("write_key", &self.write_key())?;
303        state.end()
304    }
305}
306
307impl serde::ser::Serialize for ReadKey {
308    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
309    where
310        S: serde::ser::Serializer,
311    {
312        use serde::ser::SerializeStruct;
313        let mut state = serializer.serialize_struct("read_key", 7)?;
314        state.serialize_field("external_signatures", &self.external_signatures())?;
315        state.serialize_field("internal_signatures", &self.internal_signatures())?;
316        state.serialize_field("ecdh_operation", &self.ecdh_operation())?;
317        state.serialize_field("ecdh_write_slot", &self.ecdh_write_slot())?;
318        state.end()
319    }
320}