1use crate::command::{Ecdh, SharedSecret};
2
3use super::clock_divider::ClockDivider;
4use super::command::{
5 self, GenKey, Info, Lock, NonceCtx, PrivWrite, PublicKey, Random, Serial, Word,
6};
7use super::datalink::I2c;
8use super::error::{Error, ErrorKind};
9use super::memory::{CertificateRepr, Size, Slot, Zone};
10use super::packet::{Packet, PacketBuilder, Response};
11use super::tngtls::TrustAndGo;
12use super::{Block, Digest, Signature};
13use core::cell::RefCell;
14use core::convert::TryInto;
15use core::convert::{identity, TryFrom};
16use core::fmt::Debug;
17use embedded_hal::blocking::delay::DelayUs;
18use embedded_hal::blocking::i2c::{Read, Write};
19use heapless::Vec;
20
21pub struct Verifier<'a, PHY, D>(RefCell<Verify<'a, PHY, D>>);
22
23impl<'a, PHY, D> From<Verify<'a, PHY, D>> for Verifier<'a, PHY, D> {
24 fn from(verify: Verify<'a, PHY, D>) -> Self {
25 Self(RefCell::new(verify))
26 }
27}
28
29impl<'a, PHY, D> signature::Verifier<Signature> for Verifier<'a, PHY, D>
30where
31 PHY: Read + Write,
32 <PHY as Read>::Error: Debug,
33 <PHY as Write>::Error: Debug,
34 D: DelayUs<u32>,
35{
36 fn verify(&self, msg: &[u8], signature: &Signature) -> Result<(), signature::Error> {
37 let digest = self
38 .0
39 .borrow_mut()
40 .atca
41 .sha()
42 .digest(msg)
43 .map_err(|_| signature::Error::new())?;
44 let key_id = self.0.borrow_mut().key_id.clone();
45 let public_key = self
46 .0
47 .borrow_mut()
48 .atca
49 .generate_pubkey(key_id)
50 .map_err(|_| signature::Error::new())?;
51 self.0
52 .borrow_mut()
53 .verify_digest(&digest, signature, &public_key)
54 .map_err(|_| signature::Error::new())
55 }
56}
57
58pub struct Signer<'a, PHY, D>(RefCell<Sign<'a, PHY, D>>);
59
60impl<'a, PHY, D> From<Sign<'a, PHY, D>> for Signer<'a, PHY, D> {
61 fn from(sign: Sign<'a, PHY, D>) -> Self {
62 Self(RefCell::new(sign))
63 }
64}
65
66impl<'a, PHY, D> signature::Signer<Signature> for Signer<'a, PHY, D>
67where
68 PHY: Read + Write,
69 <PHY as Read>::Error: Debug,
70 <PHY as Write>::Error: Debug,
71 D: DelayUs<u32>,
72{
73 fn try_sign(&self, msg: &[u8]) -> Result<Signature, signature::Error> {
74 let digest = self
75 .0
76 .borrow_mut()
77 .atca
78 .sha()
79 .digest(msg)
80 .map_err(|_| signature::Error::new())?;
81 self.0
82 .borrow_mut()
83 .sign_digest(&digest)
84 .map_err(|_| signature::Error::new())
85 }
86}
87
88pub struct AtCaClient<PHY, D> {
89 i2c: I2c<PHY, D>,
90 buffer: Vec<u8, 192>,
91 clock_divider: ClockDivider,
92}
93
94impl<PHY, D> AtCaClient<PHY, D> {
95 pub fn new(phy: PHY, delay: D) -> Self {
96 let i2c = I2c::new(phy, delay);
97 let buffer = Vec::new();
98 Self {
99 i2c,
100 buffer,
101 clock_divider: ClockDivider::Zero,
102 }
103 }
104
105 fn packet_builder(&mut self) -> PacketBuilder<'_> {
106 let capacity = self.buffer.capacity();
107 self.buffer.clear();
108 self.buffer
109 .resize(capacity, 0x00u8)
110 .unwrap_or_else(|()| unreachable!("Input length equals to the current capacity."));
111 PacketBuilder::new(&mut self.buffer)
112 }
113
114 pub fn memory(&mut self) -> Memory<'_, PHY, D> {
115 Memory { atca: self }
116 }
117
118 pub fn aes(&mut self, key_id: Slot) -> Aes<'_, PHY, D> {
119 Aes { atca: self, key_id }
120 }
121
122 pub fn sha(&mut self) -> Sha<'_, PHY, D> {
123 let remaining_bytes = Vec::new();
124 Sha {
125 atca: self,
126 remaining_bytes,
127 }
128 }
129
130 pub fn sign(&mut self, key_id: Slot) -> Sign<'_, PHY, D> {
131 Sign { atca: self, key_id }
132 }
133
134 pub fn verify(&mut self, key_id: Slot) -> Verify<'_, PHY, D> {
135 Verify { atca: self, key_id }
136 }
137}
138
139impl<PHY, D> AtCaClient<PHY, D>
140where
141 PHY: Read + Write,
142 <PHY as Read>::Error: Debug,
143 <PHY as Write>::Error: Debug,
144 D: DelayUs<u32>,
145{
146 fn execute(&mut self, packet: Packet) -> Result<Response<'_>, Error> {
147 let exec_time = self.clock_divider.execution_time(packet.opcode());
148 self.i2c.execute(&mut self.buffer, packet, exec_time)
149 }
150
151 pub fn signer(&mut self, key_id: Slot) -> Signer<'_, PHY, D> {
152 self.sign(key_id).into()
153 }
154
155 pub fn verifier(&mut self, key_id: Slot) -> Verifier<'_, PHY, D> {
156 self.verify(key_id).into()
157 }
158
159 pub fn tng(&mut self) -> Result<TrustAndGo<'_, PHY, D>, Error> {
160 self.try_into()
161 }
162
163 pub fn sleep(&mut self) -> Result<(), Error> {
164 self.i2c.sleep()
165 }
166
167 pub fn info(&mut self) -> Result<Word, Error> {
168 let packet = Info::new(self.packet_builder()).revision()?;
169 self.execute(packet)?.as_ref().try_into()
170 }
171
172 pub fn random(&mut self) -> Result<Block, Error> {
173 let packet = Random::new(self.packet_builder()).random()?;
174 self.execute(packet)?.as_ref().try_into()
175 }
176
177 pub fn write_message_digest_buffer(&mut self, msg: &Digest) -> Result<(), Error> {
179 let packet = NonceCtx::new(self.packet_builder()).message_digest_buffer(msg)?;
180 self.execute(packet).map(drop)
181 }
182
183 pub fn create_private_key(&mut self, key_id: Slot) -> Result<PublicKey, Error> {
185 let packet = GenKey::new(self.packet_builder()).private_key(key_id)?;
186 self.execute(packet)?.as_ref().try_into()
187 }
188
189 pub fn write_private_key(&mut self, key_id: Slot, private_key: &Block) -> Result<(), Error> {
191 let packet =
192 PrivWrite::new(self.packet_builder()).write_private_key(key_id, private_key)?;
193 self.execute(packet).map(drop)
194 }
195
196 pub fn generate_pubkey(&mut self, key_id: Slot) -> Result<PublicKey, Error> {
198 let packet = GenKey::new(self.packet_builder()).public_key(key_id)?;
199 self.execute(packet)?.as_ref().try_into()
200 }
201
202 pub fn diffie_hellman(
203 &mut self,
204 key_id: Slot,
205 public_key: PublicKey,
206 ) -> Result<SharedSecret, Error> {
207 let packet = Ecdh::new(self.packet_builder()).diffie_hellman(key_id, public_key)?;
208 self.execute(packet)?.as_ref().try_into()
209 }
210}
211
212pub struct Memory<'a, PHY, D> {
214 atca: &'a mut AtCaClient<PHY, D>,
215}
216
217impl<'a, PHY, D> Memory<'a, PHY, D> {
218 pub(crate) const SLOT_CONFIG_INDEX: usize = 20;
219 pub(crate) const CHIP_OPTIONS_INDEX: usize = 90;
220 pub(crate) const KEY_CONFIG_INDEX: usize = 96;
221}
222
223impl<'a, PHY, D> Memory<'a, PHY, D>
224where
225 PHY: Read + Write,
226 <PHY as Read>::Error: Debug,
227 <PHY as Write>::Error: Debug,
228 D: DelayUs<u32>,
229{
230 pub fn serial_number(&mut self) -> Result<Serial, Error> {
231 let packet =
232 command::Read::new(self.atca.packet_builder()).read(Zone::Config, Size::Block, 0, 0)?;
233 self.atca.execute(packet)?.as_ref().try_into()
234 }
235
236 pub fn pubkey(&mut self, key_id: Slot) -> Result<PublicKey, Error> {
237 let mut pubkey = PublicKey::default();
238 CertificateRepr::new()
239 .enumerate()
240 .scan(0, |offset, (i, ranges)| {
241 let result = command::Read::new(self.atca.packet_builder())
242 .slot(key_id, i as u8)
243 .and_then(|packet| {
244 let response = self.atca.execute(packet)?;
245 for range in ranges {
246 let dst = *offset..*offset + range.len();
247 pubkey.as_mut()[dst].copy_from_slice(&response.as_ref()[range.clone()]);
248 *offset += range.len();
249 }
250 Ok(())
251 });
252 Some(result)
253 })
254 .try_for_each(identity)
255 .map(|()| pubkey)
256 }
257
258 pub fn write_pubkey(&mut self, key_id: Slot, pubkey: impl AsRef<[u8]>) -> Result<(), Error> {
259 let mut data = Block::default();
260 CertificateRepr::new()
261 .enumerate()
262 .scan(0, |offset, (i, ranges)| {
263 data.as_mut().iter_mut().for_each(|value| *value = 0);
265
266 for range in ranges {
267 let src = *offset..*offset + range.len();
268 data.as_mut()[range.clone()].copy_from_slice(&pubkey.as_ref()[src]);
269 *offset += range.len();
270 }
271
272 let result = command::Write::new(self.atca.packet_builder())
273 .slot(key_id, i as u8, &data)
274 .and_then(|packet| self.atca.execute(packet).map(drop));
275
276 Some(result)
277 })
278 .try_for_each(identity)
279 }
280
281 pub fn write_aes_key(&mut self, key_id: Slot, aes_key: impl AsRef<[u8]>) -> Result<(), Error> {
282 let mut data = Block::default();
283 data.as_mut()[..0x10].copy_from_slice(aes_key.as_ref());
284 let packet =
285 command::Write::new(self.atca.packet_builder()).slot(key_id, 0 as u8, &data)?;
286 self.atca.execute(packet).map(drop)
287 }
288
289 pub fn is_slot_locked(&mut self, slot: Slot) -> Result<bool, Error> {
290 let zone = Zone::Config;
291 let size = Size::Word;
292 let block = 2;
293 let word_offset = 6;
294 let packet =
295 command::Read::new(self.atca.packet_builder()).read(zone, size, block, word_offset)?;
296 let response = self.atca.execute(packet)?;
297 let word = Word::try_from(response.as_ref())?;
298 let slot_locked_bytes = word.as_ref()[..2]
299 .try_into()
300 .map(u16::from_le_bytes)
301 .unwrap_or_else(|_| unreachable!());
302 Ok(slot_locked_bytes & (0x01u16 << slot as u32) == 0x00)
303 }
304
305 pub fn is_locked(&mut self, zone: Zone) -> Result<bool, Error> {
306 let size = Size::Word;
307 let block = 2;
308 let word_offset = 5;
309 let packet = command::Read::new(self.atca.packet_builder()).read(
310 Zone::Config,
311 size,
312 block,
313 word_offset,
314 )?;
315 let response = self.atca.execute(packet)?;
316 let word = Word::try_from(response.as_ref())?;
317 match zone {
318 Zone::Config => Ok(word.as_ref()[3] != 0x55),
319 Zone::Data => Ok(word.as_ref()[2] != 0x55),
320 Zone::Otp => Err(ErrorKind::BadParam.into()),
321 }
322 }
323
324 pub fn lock_slot(&mut self, key_id: Slot) -> Result<(), Error> {
325 let packet = Lock::new(self.atca.packet_builder()).slot(key_id)?;
326 self.atca.execute(packet).map(drop)
327 }
328
329 pub fn lock(&mut self, zone: Zone) -> Result<(), Error> {
330 let packet = Lock::new(self.atca.packet_builder()).zone(zone, None)?;
331 self.atca.execute(packet).map(drop)
332 }
333
334 pub fn lock_crc(&mut self, zone: Zone, crc: u16) -> Result<(), Error> {
335 let packet = Lock::new(self.atca.packet_builder()).zone(zone, Some(crc))?;
336 self.atca.execute(packet).map(drop)
337 }
338
339 pub fn chip_options(&mut self) -> Result<u16, Error> {
340 let (block, offset, pos) = Zone::locate_index(Self::CHIP_OPTIONS_INDEX);
341 let range = pos as usize..pos as usize + 2;
342 self.read_config(Size::Word, block, offset).map(|resp| {
343 resp.as_ref()[range]
344 .try_into()
345 .map(u16::from_le_bytes)
346 .unwrap_or_else(|_| unreachable!())
347 })
348 }
349
350 pub fn permission(&mut self, slot: Slot) -> Result<u16, Error> {
351 let index = Self::SLOT_CONFIG_INDEX + (slot as usize * 2);
352 let (block, offset, pos) = Zone::locate_index(index);
353 let range = pos as usize..pos as usize + 2;
354 self.read_config(Size::Word, block, offset).map(|resp| {
355 resp.as_ref()[range]
356 .try_into()
357 .map(u16::from_le_bytes)
358 .unwrap_or_else(|_| unreachable!())
359 })
360 }
361
362 pub fn key_type(&mut self, slot: Slot) -> Result<u16, Error> {
363 let index = Self::KEY_CONFIG_INDEX + (slot as usize * 2);
364 let (block, offset, pos) = Zone::locate_index(index);
365 let range = pos as usize..pos as usize + 2;
366 self.read_config(Size::Word, block, offset).map(|resp| {
367 resp.as_ref()[range]
368 .try_into()
369 .map(u16::from_le_bytes)
370 .unwrap_or_else(|_| unreachable!())
371 })
372 }
373
374 pub fn read_config(
376 &mut self,
377 size: Size,
378 block: u8,
379 offset: u8,
380 ) -> Result<Response<'_>, Error> {
381 let packet = command::Read::new(self.atca.packet_builder()).read(
382 Zone::Config,
383 size,
384 block,
385 offset,
386 )?;
387 self.atca.execute(packet)
388 }
389
390 pub fn write_config(
391 &mut self,
392 size: Size,
393 block: u8,
394 offset: u8,
395 data: impl AsRef<[u8]>,
396 ) -> Result<(), Error> {
397 let packet = command::Write::new(self.atca.packet_builder()).write(
398 Zone::Config,
399 size,
400 block,
401 offset,
402 data,
403 )?;
404 self.atca.execute(packet).map(drop)
405 }
406}
407
408pub struct Aes<'a, PHY, D> {
411 atca: &'a mut AtCaClient<PHY, D>,
412 key_id: Slot,
413}
414
415impl<'a, PHY, D> Aes<'a, PHY, D>
416where
417 PHY: Read + Write,
418 <PHY as Read>::Error: Debug,
419 <PHY as Write>::Error: Debug,
420 D: DelayUs<u32>,
421{
422 pub fn encrypt(&mut self, plaintext: &[u8], ciphertext: &mut [u8]) -> Result<(), Error> {
423 use command::Aes as AesCmd;
424
425 if plaintext.len() != ciphertext.len() {
426 return Err(ErrorKind::BadParam.into());
427 }
428
429 for (plain, cipher) in plaintext
430 .chunks(AesCmd::DATA_SIZE)
431 .zip(ciphertext.chunks_mut(AesCmd::DATA_SIZE))
432 {
433 let packet = AesCmd::new(self.atca.packet_builder()).encrypt(self.key_id, plain)?;
437
438 let response = self.atca.execute(packet)?;
440 if response.as_ref().len() != AesCmd::DATA_SIZE {
441 return Err(ErrorKind::InvalidSize.into());
442 }
443 cipher.copy_from_slice(response.as_ref());
444 }
445 Ok(())
446 }
447
448 pub fn decrypt(&mut self, ciphertext: &[u8], plaintext: &mut [u8]) -> Result<(), Error> {
449 use command::Aes as AesCmd;
450
451 if ciphertext.len() != plaintext.len() {
452 return Err(ErrorKind::BadParam.into());
453 }
454
455 for (cipher, plain) in ciphertext
456 .chunks(AesCmd::DATA_SIZE)
457 .zip(plaintext.chunks_mut(AesCmd::DATA_SIZE))
458 {
459 let packet = AesCmd::new(self.atca.packet_builder()).decrypt(self.key_id, cipher)?;
463
464 let response = self.atca.execute(packet)?;
466 if response.as_ref().len() != AesCmd::DATA_SIZE {
467 return Err(ErrorKind::InvalidSize.into());
468 }
469 plain.copy_from_slice(response.as_ref());
470 }
471 Ok(())
472 }
473}
474
475pub struct Sha<'a, PHY, D> {
477 atca: &'a mut AtCaClient<PHY, D>,
478 remaining_bytes: Vec<u8, 64>,
479}
480
481impl<'a, PHY, D> Sha<'a, PHY, D>
482where
483 PHY: Read + Write,
484 <PHY as Read>::Error: Debug,
485 <PHY as Write>::Error: Debug,
486 D: DelayUs<u32>,
487{
488 pub fn init(&mut self) -> Result<(), Error> {
489 let packet = command::Sha::new(self.atca.packet_builder()).start()?;
490 self.atca.execute(packet).map(drop)
491 }
492
493 pub fn update(&mut self, data: impl AsRef<[u8]>) -> Result<(), Error> {
495 let capacity = 0x40;
496 let length = data.as_ref().len();
497
498 let remainder_length = data.as_ref().len() % capacity;
500 let (bytes, remainder) = data.as_ref().split_at(length - remainder_length);
501 self.remaining_bytes.extend_from_slice(remainder).ok();
502
503 bytes.chunks(capacity).try_for_each(|chunk| {
505 let packet = command::Sha::new(self.atca.packet_builder()).update(chunk)?;
506 self.atca.execute(packet).map(drop)
507 })
508 }
509
510 pub fn chain(&mut self, data: impl AsRef<[u8]>) -> Result<&mut Self, Error> {
511 if self.remaining_bytes.len() != 0 {
512 }
514
515 self.update(data)?;
516 Ok(self)
517 }
518
519 pub fn finalize(&mut self) -> Result<Digest, Error> {
520 let packet = command::Sha::new(self.atca.packet_builder()).end(&self.remaining_bytes)?;
521 self.atca.execute(packet)?.as_ref().try_into()
522 }
523
524 pub fn digest(&mut self, data: &[u8]) -> Result<Digest, Error> {
525 self.init()?;
526 self.update(data)?;
527 self.finalize()
528 }
529}
530
531pub struct Sign<'a, PHY, D> {
534 atca: &'a mut AtCaClient<PHY, D>,
535 key_id: Slot,
536}
537
538impl<'a, PHY, D> Sign<'a, PHY, D>
539where
540 PHY: Read + Write,
541 <PHY as Read>::Error: Debug,
542 <PHY as Write>::Error: Debug,
543 D: DelayUs<u32>,
544{
545 pub fn sign_digest(&mut self, digest: &Digest) -> Result<Signature, Error> {
548 self.atca.random()?;
550 self.atca.write_message_digest_buffer(digest)?;
552 let packet = command::Sign::new(self.atca.packet_builder()).external(self.key_id)?;
554 self.atca.execute(packet)?.as_ref().try_into()
555 }
556}
557
558pub struct Verify<'a, PHY, D> {
559 atca: &'a mut AtCaClient<PHY, D>,
560 key_id: Slot,
561}
562
563impl<'a, PHY, D> Verify<'a, PHY, D>
564where
565 PHY: Read + Write,
566 <PHY as Read>::Error: Debug,
567 <PHY as Write>::Error: Debug,
568 D: DelayUs<u32>,
569{
570 pub fn verify_digest(
573 &mut self,
574 digest: &Digest,
575 signature: &Signature,
576 public_key: &PublicKey,
577 ) -> Result<(), Error> {
578 self.atca.write_message_digest_buffer(digest)?;
580 let packet =
582 command::Verify::new(self.atca.packet_builder()).external(signature, public_key)?;
583 self.atca.execute(packet).map(drop)
584 }
585}