1use super::client::{AtCaClient, Memory, Sha};
10use super::error::Error;
11use super::memory::{Size, Slot, Zone};
12use core::convert::TryFrom;
13use core::fmt::Debug;
14use digest::{FixedOutputDirty, Reset, Update};
15use embedded_hal::blocking::delay::DelayUs;
16use embedded_hal::blocking::i2c::{Read, Write};
17use generic_array::typenum::U32;
18use generic_array::GenericArray;
19
20pub const AUTH_PRIVATE_KEY: Slot = Slot::PrivateKey00;
21pub const SIGN_PRIVATE_KEY: Slot = Slot::PrivateKey01;
22pub const USER_PRIVATE_KEY1: Slot = Slot::PrivateKey02;
23pub const USER_PRIVATE_KEY2: Slot = Slot::PrivateKey03;
24pub const USER_PRIVATE_KEY3: Slot = Slot::PrivateKey04;
25pub const IO_PROTECTION_KEY: Slot = Slot::PrivateKey06;
26pub const AES_KEY: Slot = Slot::Certificate09;
27pub const DEVICE_CERTIFICATE: Slot = Slot::Certificate0a;
28pub const SIGNER_PUBLIC_KEY: Slot = Slot::Certificate0b;
29pub const SIGNER_CERTIFICATE: Slot = Slot::Certificate0c;
30
31pub struct Hasher<'a, PHY, D>(Sha<'a, PHY, D>);
32impl<'a, PHY, D> From<Sha<'a, PHY, D>> for Hasher<'a, PHY, D> {
33 fn from(sha: Sha<'a, PHY, D>) -> Self {
34 Self(sha)
35 }
36}
37
38impl<'a, PHY, D> Clone for Hasher<'a, PHY, D> {
39 fn clone(&self) -> Self {
40 unimplemented!()
41 }
42}
43
44impl<'a, PHY, D> Default for Hasher<'a, PHY, D> {
45 fn default() -> Self {
46 unimplemented!()
47 }
48}
49
50impl<'a, PHY, D> Update for Hasher<'a, PHY, D>
51where
52 PHY: Read + Write,
53 <PHY as Read>::Error: Debug,
54 <PHY as Write>::Error: Debug,
55 D: DelayUs<u32>,
56{
57 fn update(&mut self, data: impl AsRef<[u8]>) {
58 self.0.update(data).expect("update operation failed");
59 }
60}
61
62impl<'a, PHY, D> FixedOutputDirty for Hasher<'a, PHY, D>
63where
64 PHY: Read + Write,
65 <PHY as Read>::Error: Debug,
66 <PHY as Write>::Error: Debug,
67 D: DelayUs<u32>,
68{
69 type OutputSize = U32;
70 fn finalize_into_dirty(&mut self, out: &mut GenericArray<u8, Self::OutputSize>) {
71 let digest = self.0.finalize().expect("finalize operation failed");
72 out.as_mut_slice().copy_from_slice(digest.as_ref());
73 }
74}
75
76impl<'a, PHY, D> Reset for Hasher<'a, PHY, D>
77where
78 PHY: Read + Write,
79 <PHY as Read>::Error: Debug,
80 <PHY as Write>::Error: Debug,
81 D: DelayUs<u32>,
82{
83 fn reset(&mut self) {}
84}
85
86pub struct TrustAndGo<'a, PHY, D> {
87 atca: &'a mut AtCaClient<PHY, D>,
88}
89
90impl<'a, PHY, D> TrustAndGo<'a, PHY, D> {
91 const TNG_TLS_SLOT_CONFIG_DATA: [u8; Size::Block as usize] = [
93 0x85, 0x00, 0x82, 0x00, 0x85, 0x20, 0x85, 0x20, 0x85, 0x20, 0x8f, 0x8f, 0x8f, 0x0f, 0xaf, 0x8f, 0x0f, 0x0f, 0x8f, 0x0f, 0x0f, 0x8f, 0x0f, 0x8f, 0x0f, 0x8f, 0x00, 0x00, 0x00, 0x00, 0xaf, 0x8f, ];
107
108 const TNG_TLS_CHIP_OPTIONS: [u8; Size::Word as usize] = [
109 0xff, 0xff, 0x60, 0x0e,
111 ];
112
113 const TNG_TLS_KEY_CONFIG_DATA: [u8; Size::Block as usize] = [
114 0x53, 0x00, 0x53, 0x00, 0x73, 0x00, 0x73, 0x00, 0x73, 0x00, 0x1c, 0x00, 0x7c, 0x00, 0x3c, 0x00, 0x3c, 0x00, 0x1a, 0x00, 0x1c, 0x00, 0x10, 0x00, 0x1c, 0x00, 0x3c, 0x00, 0x3c, 0x00, 0x1c, 0x00, ];
128}
129
130impl<'a, PHY, D> TrustAndGo<'a, PHY, D>
132where
133 PHY: Read + Write,
134 <PHY as Read>::Error: Debug,
135 <PHY as Write>::Error: Debug,
136 D: DelayUs<u32>,
137{
138 pub fn configure_permissions(&mut self) -> Result<(), Error> {
140 Self::TNG_TLS_SLOT_CONFIG_DATA
141 .chunks(Size::Word.len())
142 .enumerate()
143 .try_for_each(|(i, word)| {
144 let index = Memory::<PHY, D>::SLOT_CONFIG_INDEX + i * Size::Word.len();
145 let (block, offset, _) = Zone::locate_index(index);
146 self.atca
147 .memory()
148 .write_config(Size::Word, block, offset, word)
149 .map(drop)
150 })
151 }
152
153 pub fn configure_chip_options(&mut self) -> Result<(), Error> {
155 let (block, offset, _) = Zone::locate_index(Memory::<PHY, D>::CHIP_OPTIONS_INDEX);
156 self.atca
157 .memory()
158 .write_config(Size::Word, block, offset, &Self::TNG_TLS_CHIP_OPTIONS)
159 }
160
161 pub fn configure_key_types(&mut self) -> Result<(), Error> {
163 let (block, offset, _) = Zone::locate_index(Memory::<PHY, D>::KEY_CONFIG_INDEX);
164 self.atca
165 .memory()
166 .write_config(Size::Block, block, offset, &Self::TNG_TLS_KEY_CONFIG_DATA)
167 }
168}
169
170impl<'a, PHY, D> TryFrom<&'a mut AtCaClient<PHY, D>> for TrustAndGo<'a, PHY, D>
172where
173 PHY: Read + Write,
174 <PHY as Read>::Error: Debug,
175 <PHY as Write>::Error: Debug,
176 D: DelayUs<u32>,
177{
178 type Error = Error;
179 fn try_from(atca: &'a mut AtCaClient<PHY, D>) -> Result<Self, Self::Error> {
180 let mut tng = Self { atca };
181 if !tng.atca.memory().is_locked(Zone::Config)? {
183 tng.configure_permissions()?;
184 tng.configure_chip_options()?;
185 tng.configure_key_types()?;
186 tng.atca.memory().lock(Zone::Config)?;
188 }
189
190 if !tng.atca.memory().is_locked(Zone::Data)? {
192 #[cfg(not(debug_assertions))]
194 tng.atca.memory().lock(Zone::Data)?;
195 }
196
197 Ok(tng)
198 }
199}
200
201#[cfg(test)]
202mod tests {
203 use super::*;
204 use crate::command::OpCode;
205 use core::convert::TryInto;
206 use core::ops::Deref;
207 use heapless::Vec;
208 use OpCode::*;
209 const KEY_TYPE_P256: u16 = 0x04; const KEY_TYPE_AES: u16 = 0x06; const KEY_TYPE_SHA: u16 = 0x07; struct Provision {
214 key_id: Slot,
215 permission: u16,
216 key_config: u16,
217 }
218
219 impl Provision {
220 fn new(key_id: Slot) -> Self {
221 let permission = permission(key_id);
222 let key_config = key_config(key_id);
223 Self {
224 key_id,
225 permission,
226 key_config,
227 }
228 }
229
230 fn is_private(&self) -> bool {
231 self.key_config & 0x01 != 0x00
232 }
233
234 fn key_type(&self) -> u16 {
235 (self.key_config >> 2) & 0x07
236 }
237
238 fn read_key(&self) -> u16 {
239 self.permission & 0x0f
240 }
241
242 fn encrypt_read(&self) -> bool {
243 (self.permission >> 6) & 0x01 != 0x00
244 }
245
246 fn is_secret(&self) -> bool {
247 (self.permission >> 7) & 0x01 != 0x00
248 }
249
250 fn write_config(&self) -> u16 {
251 (self.permission >> 12) & 0x0f
252 }
253
254 fn read_permission(&self) -> &str {
255 match (self.is_secret(), self.encrypt_read()) {
256 (false, false) => "Clear text",
257 (true, false) => "Never",
258 (true, true) => "Encrypted",
259 _ => panic!("Prohibited"),
260 }
261 }
262
263 fn write_permission(&self) -> &str {
264 match self.write_config() {
265 0x00 => "Clear text",
266 0x01 => "PubInvalid",
267 x if (x >> 1) == 0x01 => "Never",
268 x if (x >> 2) == 0x02 => "Never",
269 x if (x >> 2) & 0x01 == 0x01 => "Encrypted",
270 _ => panic!("Prohibited"),
271 }
272 }
273
274 fn require_nonce(&self) -> bool {
276 (self.key_config >> 6) & 0x01 != 0x00
277 }
278
279 fn creation_commands(&self) -> Vec<OpCode, 5> {
281 let mut commands = Vec::<OpCode, 5>::new();
282 if self.key_id.is_private_key() && self.key_type() == KEY_TYPE_P256 && self.is_secret()
283 {
284 if (self.write_config() >> 1) & 0x01 == 0x01 {
285 commands.push(GenKey).unwrap();
286 commands.push(DeriveKey).unwrap();
287 }
288 if (self.write_config() >> 2) & 0x01 == 0x01 {
289 commands.push(PrivWrite).unwrap();
290 }
291 }
292 commands
293 }
294
295 #[allow(dead_code)]
297 fn operation_commands(&self) -> &[OpCode] {
298 let mut commands = Vec::<OpCode, 5>::new();
299 if self.key_id.is_private_key() {
300 if (self.read_key() >> 2) & 0x01 == 0x01 {
301 commands.push(Ecdh).unwrap();
302 }
303 if self.is_secret() && self.key_type() == KEY_TYPE_P256 {
304 commands.push(Sign).unwrap();
305 }
306 unimplemented!()
307 } else {
308 unimplemented!()
309 }
310 }
311 }
312
313 fn permission(key_id: Slot) -> u16 {
314 let data = &TrustAndGo::<(), ()>::TNG_TLS_SLOT_CONFIG_DATA;
315 let index = key_id as usize * 2;
316 let range = index..index + 2;
317 data[range]
318 .try_into()
319 .map(u16::from_le_bytes)
320 .unwrap_or_else(|_| unreachable!())
321 }
322
323 fn key_config(key_id: Slot) -> u16 {
324 let data = &TrustAndGo::<(), ()>::TNG_TLS_KEY_CONFIG_DATA;
325 let index = key_id as usize * 2;
326 let range = index..index + 2;
327 data[range]
328 .try_into()
329 .map(u16::from_le_bytes)
330 .unwrap_or_else(|_| unreachable!())
331 }
332
333 #[test]
337 fn provision() {
338 let auth_priv = Provision::new(AUTH_PRIVATE_KEY);
339 assert_eq!(true, auth_priv.is_private());
340 assert_eq!(KEY_TYPE_P256, auth_priv.key_type());
341 assert_eq!(true, auth_priv.require_nonce());
342 assert_eq!(0x05, auth_priv.read_key());
343 assert_eq!("Clear text", auth_priv.write_permission());
344 assert_eq!(0, auth_priv.creation_commands().len());
345
346 let sign_priv = Provision::new(SIGN_PRIVATE_KEY);
347 assert_eq!(true, sign_priv.is_private());
348 assert_eq!(KEY_TYPE_P256, sign_priv.key_type());
349 assert_eq!(true, sign_priv.require_nonce());
350 assert_eq!(0x02, sign_priv.read_key());
351 assert_eq!("Clear text", sign_priv.write_permission());
352 assert_eq!(0, sign_priv.creation_commands().len());
353
354 for key_id in [USER_PRIVATE_KEY1, USER_PRIVATE_KEY2, USER_PRIVATE_KEY3].iter() {
355 let user_priv = Provision::new(*key_id);
356 assert_eq!(true, user_priv.is_private());
357 assert_eq!(KEY_TYPE_P256, user_priv.key_type());
358 assert_eq!(true, user_priv.require_nonce());
359 assert_eq!(0x05, user_priv.read_key());
360 assert_eq!("Never", user_priv.write_permission());
361 assert_eq!(&[GenKey, DeriveKey], user_priv.creation_commands().deref());
362 }
363
364 let io_protect = Provision::new(IO_PROTECTION_KEY);
365 assert_eq!(KEY_TYPE_SHA, io_protect.key_type());
366 assert_eq!("Clear text", io_protect.write_permission());
367 assert_eq!(true, io_protect.require_nonce());
368 assert_eq!(0, io_protect.creation_commands().len());
369
370 let aes_key = Provision::new(AES_KEY);
371 assert_eq!(KEY_TYPE_AES, aes_key.key_type());
372 assert_eq!("Never", aes_key.read_permission());
373 assert_eq!("Clear text", aes_key.write_permission());
374 assert_eq!(0x00, aes_key.write_config());
375
376 let device_cert = Provision::new(DEVICE_CERTIFICATE);
377 assert_eq!(KEY_TYPE_SHA, device_cert.key_type());
378 assert_eq!("Clear text", device_cert.read_permission());
379 assert_eq!("Never", device_cert.write_permission());
380 assert_eq!(0x08, device_cert.write_config());
381
382 let signer_pub = Provision::new(SIGNER_PUBLIC_KEY);
383 assert_eq!(KEY_TYPE_P256, signer_pub.key_type());
384 assert_eq!("Clear text", signer_pub.read_permission());
385 assert_eq!("Never", signer_pub.write_permission());
386 assert_eq!(0x08, signer_pub.write_config());
387
388 let signer_cert = Provision::new(SIGNER_CERTIFICATE);
389 assert_eq!(KEY_TYPE_SHA, signer_cert.key_type());
390 assert_eq!("Clear text", signer_cert.read_permission());
391 assert_eq!("Never", signer_cert.write_permission());
392 assert_eq!(0x08, signer_cert.write_config());
393 }
394}