at_cryptoauth/
command.rs

1// Command definitions
2// Overall structure is modeled after https://github.com/tokio-rs/mini-redis/blob/master/src/cmd/mod.rs
3use super::error::{Error, ErrorKind};
4use super::memory::{Size, Slot, Zone};
5use super::packet::{Packet, PacketBuilder};
6use core::convert::TryFrom;
7use generic_array::typenum::{U32, U4, U64, U9};
8use generic_array::GenericArray;
9
10// Encapsulates raw 4 bytes. When it is a return value of `info`, it contains
11// the device's revision number.
12#[derive(Clone, Copy, Debug, Default)]
13pub struct Word {
14    value: GenericArray<u8, U4>,
15}
16
17impl TryFrom<&[u8]> for Word {
18    type Error = Error;
19    fn try_from(buffer: &[u8]) -> Result<Self, Self::Error> {
20        if buffer.len() != Size::Word.len() {
21            return Err(ErrorKind::BadParam.into());
22        }
23
24        let mut value = Self::default();
25        value.as_mut().copy_from_slice(buffer);
26        Ok(value)
27    }
28}
29
30impl AsRef<[u8]> for Word {
31    fn as_ref(&self) -> &[u8] {
32        self.value.as_ref()
33    }
34}
35
36impl AsMut<[u8]> for Word {
37    fn as_mut(&mut self) -> &mut [u8] {
38        self.value.as_mut()
39    }
40}
41
42// Encapsulates raw 32 bytes.
43#[derive(Clone, Copy, Debug, Default)]
44pub struct Block {
45    value: GenericArray<u8, U32>,
46}
47
48impl TryFrom<&[u8]> for Block {
49    type Error = Error;
50    fn try_from(buffer: &[u8]) -> Result<Self, Self::Error> {
51        if buffer.len() != Size::Block.len() {
52            return Err(ErrorKind::BadParam.into());
53        }
54
55        let mut value = Self::default();
56        value.as_mut().copy_from_slice(buffer);
57        Ok(value)
58    }
59}
60
61impl AsRef<[u8]> for Block {
62    fn as_ref(&self) -> &[u8] {
63        self.value.as_ref()
64    }
65}
66
67impl AsMut<[u8]> for Block {
68    fn as_mut(&mut self) -> &mut [u8] {
69        self.value.as_mut()
70    }
71}
72
73// Represents a serial number consisting of 9 bytes. Its uniqueness is
74// guaranteed. A return type of API `read_serial`.
75#[derive(Clone, Copy, Debug, Default)]
76pub struct Serial {
77    value: GenericArray<u8, U9>,
78}
79
80impl TryFrom<&[u8]> for Serial {
81    type Error = Error;
82    fn try_from(buffer: &[u8]) -> Result<Self, Self::Error> {
83        if buffer.len() != Size::Block.len() {
84            return Err(ErrorKind::BadParam.into());
85        }
86
87        let mut value = [0x00; 9];
88        value[0..4].as_mut().copy_from_slice(&buffer[0..4]);
89        value[4..9].as_mut().copy_from_slice(&buffer[8..13]);
90        Ok(Self {
91            value: value.into(),
92        })
93    }
94}
95
96impl AsRef<[u8]> for Serial {
97    fn as_ref(&self) -> &[u8] {
98        self.value.as_ref()
99    }
100}
101
102impl AsMut<[u8]> for Serial {
103    fn as_mut(&mut self) -> &mut [u8] {
104        self.value.as_mut()
105    }
106}
107
108/// A public key signature returned from a signing operation. Format is R and
109/// S integers in big-endian format. 64 bytes for P256 curve.
110#[derive(Clone, Copy, Debug, Default)]
111pub struct Signature {
112    value: GenericArray<u8, U64>,
113}
114
115impl AsRef<[u8]> for Signature {
116    fn as_ref(&self) -> &[u8] {
117        self.value.as_ref()
118    }
119}
120
121impl AsMut<[u8]> for Signature {
122    fn as_mut(&mut self) -> &mut [u8] {
123        self.value.as_mut()
124    }
125}
126
127impl TryFrom<&[u8]> for Signature {
128    type Error = Error;
129    fn try_from(buffer: &[u8]) -> Result<Self, Self::Error> {
130        if buffer.len() != 0x40 {
131            return Err(ErrorKind::BadParam.into());
132        }
133
134        let mut value = Self::default();
135        value.as_mut().copy_from_slice(buffer);
136        Ok(value)
137    }
138}
139
140impl signature::Signature for Signature {
141    fn from_bytes(bytes: &[u8]) -> Result<Self, signature::Error> {
142        Self::try_from(bytes).map_err(|_| signature::Error::new())
143    }
144}
145
146#[derive(Clone, Copy, Debug, Default)]
147pub struct PublicKey {
148    value: GenericArray<u8, U64>,
149}
150
151impl AsRef<[u8]> for PublicKey {
152    fn as_ref(&self) -> &[u8] {
153        self.value.as_ref()
154    }
155}
156
157impl AsMut<[u8]> for PublicKey {
158    fn as_mut(&mut self) -> &mut [u8] {
159        self.value.as_mut()
160    }
161}
162
163impl TryFrom<&[u8]> for PublicKey {
164    type Error = Error;
165    fn try_from(buffer: &[u8]) -> Result<Self, Self::Error> {
166        if buffer.len() != 0x40 {
167            return Err(ErrorKind::BadParam.into());
168        }
169
170        let mut value = Self::default();
171        value.as_mut().copy_from_slice(buffer);
172        Ok(value)
173    }
174}
175
176#[derive(Clone, Copy, Debug, Default)]
177pub struct SharedSecret {
178    value: GenericArray<u8, U32>,
179}
180
181impl AsRef<[u8]> for SharedSecret {
182    fn as_ref(&self) -> &[u8] {
183        self.value.as_ref()
184    }
185}
186
187impl AsMut<[u8]> for SharedSecret {
188    fn as_mut(&mut self) -> &mut [u8] {
189        self.value.as_mut()
190    }
191}
192
193impl TryFrom<&[u8]> for SharedSecret {
194    type Error = Error;
195    fn try_from(buffer: &[u8]) -> Result<Self, Self::Error> {
196        if buffer.len() != 32 {
197            return Err(ErrorKind::BadParam.into());
198        }
199
200        let mut value = Self::default();
201        value.as_mut().copy_from_slice(buffer);
202        Ok(value)
203    }
204}
205
206// A digest yielded from cryptographic hash functions. Merely a wrapper around
207// `GenericArray<u8, 32>` of `digest` crate.
208#[derive(Clone, Copy, Debug, Default)]
209pub struct Digest {
210    value: GenericArray<u8, U32>,
211}
212
213impl TryFrom<&[u8]> for Digest {
214    type Error = Error;
215    fn try_from(buffer: &[u8]) -> Result<Self, Self::Error> {
216        if buffer.len() != 32 {
217            return Err(ErrorKind::BadParam.into());
218        }
219
220        let mut value = Self::default();
221        value.as_mut().copy_from_slice(buffer);
222        Ok(value)
223    }
224}
225
226impl AsRef<[u8]> for Digest {
227    fn as_ref(&self) -> &[u8] {
228        self.value.as_ref()
229    }
230}
231
232impl AsMut<[u8]> for Digest {
233    fn as_mut(&mut self) -> &mut [u8] {
234        self.value.as_mut()
235    }
236}
237
238#[derive(Clone, Copy, Debug, PartialEq, Eq)]
239pub(crate) enum OpCode {
240    /// CheckMac command op-code
241    #[allow(dead_code)]
242    CheckMac = 0x28,
243    /// DeriveKey command op-code
244    #[allow(dead_code)]
245    DeriveKey = 0x1C,
246    /// Info command op-code
247    Info = 0x30,
248    /// GenDig command op-code
249    GenDig = 0x15,
250    /// GenKey command op-code
251    GenKey = 0x40,
252    /// HMAC command op-code
253    #[allow(dead_code)]
254    HMac = 0x11,
255    /// Lock command op-code
256    Lock = 0x17,
257    /// MAC command op-code
258    #[allow(dead_code)]
259    Mac = 0x08,
260    /// Nonce command op-code
261    Nonce = 0x16,
262    /// Pause command op-code
263    #[allow(dead_code)]
264    Pause = 0x01,
265    /// PrivWrite command op-code
266    PrivWrite = 0x46,
267    /// Random command op-code
268    Random = 0x1B,
269    /// Read command op-code
270    Read = 0x02,
271    /// Sign command op-code
272    Sign = 0x41,
273    /// UpdateExtra command op-code
274    #[allow(dead_code)]
275    UpdateExtra = 0x20,
276    /// Verify command op-code
277    Verify = 0x45,
278    /// Write command op-code
279    Write = 0x12,
280    /// ECDH command op-code
281    #[allow(dead_code)]
282    Ecdh = 0x43,
283    /// Counter command op-code
284    #[allow(dead_code)]
285    Counter = 0x24,
286    /// SHA command op-code
287    Sha = 0x47,
288    /// AES command op-code
289    Aes = 0x51,
290    /// KDF command op-code
291    #[allow(dead_code)]
292    Kdf = 0x56,
293    /// Secure Boot command op-code
294    #[allow(dead_code)]
295    SecureBoot = 0x80,
296    /// Self test command op-code
297    #[allow(dead_code)]
298    SelfTest = 0x77,
299}
300
301#[allow(dead_code)]
302pub(crate) struct CheckMac<'a>(PacketBuilder<'a>);
303#[allow(dead_code)]
304pub(crate) struct Counter<'a>(PacketBuilder<'a>);
305#[allow(dead_code)]
306pub(crate) struct DeriveKey<'a>(PacketBuilder<'a>);
307#[allow(dead_code)]
308pub(crate) struct Ecdh<'a>(PacketBuilder<'a>);
309pub(crate) struct GenDig<'a>(PacketBuilder<'a>);
310pub(crate) struct GenKey<'a>(PacketBuilder<'a>);
311#[allow(dead_code)]
312pub(crate) struct HMac<'a>(PacketBuilder<'a>);
313pub(crate) struct Info<'a>(PacketBuilder<'a>);
314pub(crate) struct Lock<'a>(PacketBuilder<'a>);
315#[allow(dead_code)]
316pub(crate) struct Mac<'a>(PacketBuilder<'a>);
317pub(crate) struct NonceCtx<'a> {
318    builder: PacketBuilder<'a>,
319    #[allow(dead_code)]
320    counter: u32,
321}
322#[allow(dead_code)]
323pub(crate) struct Pause<'a>(PacketBuilder<'a>);
324
325// For best security, it is recommended that the `PrivWrite` command not be
326// used, and that private keys be internally generated from the RNG using the
327// `GenKey` command.
328pub(crate) struct PrivWrite<'a>(PacketBuilder<'a>);
329pub(crate) struct Random<'a>(PacketBuilder<'a>);
330pub(crate) struct Read<'a>(PacketBuilder<'a>);
331pub(crate) struct Sign<'a>(PacketBuilder<'a>);
332#[allow(dead_code)]
333pub(crate) struct UpdateExtra<'a>(PacketBuilder<'a>);
334pub(crate) struct Verify<'a>(PacketBuilder<'a>);
335pub(crate) struct Write<'a>(PacketBuilder<'a>);
336pub(crate) struct Sha<'a>(PacketBuilder<'a>);
337pub(crate) struct Aes<'a>(PacketBuilder<'a>);
338#[allow(dead_code)]
339pub(crate) struct Kdf<'a>(PacketBuilder<'a>);
340#[allow(dead_code)]
341pub(crate) struct SecureBoot<'a>(PacketBuilder<'a>);
342#[allow(dead_code)]
343pub(crate) struct SelfTest<'a>(PacketBuilder<'a>);
344
345#[allow(dead_code)]
346impl<'a> Ecdh<'a> {
347    pub(crate) fn new(builder: PacketBuilder<'a>) -> Self {
348        Self(builder)
349    }
350
351    pub(crate) fn diffie_hellman(
352        &mut self,
353        private_key_id: Slot,
354        public_key: PublicKey,
355    ) -> Result<Packet, Error> {
356        let packet = self
357            .0
358            .opcode(OpCode::Ecdh)
359            .mode(0x00)
360            .param2(private_key_id as u16)
361            .pdu_data(public_key)
362            .build()?;
363        Ok(packet)
364    }
365}
366
367// Used when signing an internally stored digest. The GenDig command uses
368// SHA-256 to combine a stored value with the contents of TempKey, which must
369// have been valid prior to the execution of this command.
370#[allow(dead_code)]
371impl<'a> GenDig<'a> {
372    pub(crate) fn new(builder: PacketBuilder<'a>) -> Self {
373        Self(builder)
374    }
375
376    pub(crate) fn gendig(&mut self, key_id: Slot) -> Result<Packet, Error> {
377        let packet = self
378            .0
379            .opcode(OpCode::GenDig)
380            .param2(key_id as u16)
381            .build()?;
382        Ok(packet)
383    }
384}
385
386/// GenKey
387impl<'a> GenKey<'a> {
388    // Config zone should be locked, otherwise GenKey always fails regardless of
389    // a mode parameter.
390    const MODE_PRIVATE: u8 = 0x04; // Private key generation
391    const MODE_PUBLIC: u8 = 0x00; // Public key calculation
392    #[allow(dead_code)]
393    const MODE_DIGEST: u8 = 0x08; // PubKey digest will be created after the public key is calculated
394    #[allow(dead_code)]
395    const MODE_PUBKEY_DIGEST: u8 = 0x10; // Calculate a digest on the public key
396
397    pub(crate) fn new(builder: PacketBuilder<'a>) -> Self {
398        Self(builder)
399    }
400
401    pub(crate) fn private_key(&mut self, key_id: Slot) -> Result<Packet, Error> {
402        let packet = self
403            .0
404            .opcode(OpCode::GenKey)
405            .mode(Self::MODE_PRIVATE)
406            .param2(key_id as u16)
407            .build()?;
408        Ok(packet)
409    }
410
411    pub(crate) fn public_key(&mut self, key_id: Slot) -> Result<Packet, Error> {
412        let packet = self
413            .0
414            .opcode(OpCode::GenKey)
415            .mode(Self::MODE_PUBLIC)
416            .param2(key_id as u16)
417            .build()?;
418        Ok(packet)
419    }
420}
421
422impl<'a> Info<'a> {
423    // Info mode Revision
424    const MODE_REVISION: u8 = 0x00;
425
426    pub(crate) fn new(builder: PacketBuilder<'a>) -> Self {
427        Self(builder)
428    }
429
430    /// Command execution will return a word containing the revision.
431    pub(crate) fn revision(&mut self) -> Result<Packet, Error> {
432        let packet = self
433            .0
434            .opcode(OpCode::Info)
435            .mode(Self::MODE_REVISION)
436            .build()?;
437        Ok(packet)
438    }
439}
440
441impl<'a> Lock<'a> {
442    const LOCK_ZONE_NO_CRC: u8 = 0x80;
443
444    pub(crate) fn new(builder: PacketBuilder<'a>) -> Self {
445        Self(builder)
446    }
447
448    pub(crate) fn zone(&mut self, zone: Zone, crc: Option<u16>) -> Result<Packet, Error> {
449        if matches!(zone, Zone::Otp) {
450            return Err(ErrorKind::BadParam.into());
451        }
452
453        let packet = match crc {
454            None => self
455                .0
456                .opcode(OpCode::Lock)
457                .mode(Self::LOCK_ZONE_NO_CRC | zone as u8)
458                .build()?,
459            Some(crc) => self
460                .0
461                .opcode(OpCode::Lock)
462                .mode(zone as u8)
463                .param2(crc)
464                .build()?,
465        };
466
467        Ok(packet)
468    }
469
470    pub(crate) fn slot(&mut self, key_id: Slot) -> Result<Packet, Error> {
471        let mode = (key_id as u8) << 2 | 0x02 | Self::LOCK_ZONE_NO_CRC;
472        let packet = self.0.opcode(OpCode::Lock).mode(mode).build()?;
473        Ok(packet)
474    }
475}
476
477/// Nonce
478impl<'a> NonceCtx<'a> {
479    #[allow(dead_code)]
480    const MODE_MASK: u8 = 0x03; // Nonce mode bits 2 to 7 are 0.
481    #[allow(dead_code)]
482    const MODE_SEED_UPDATE: u8 = 0x00; // Nonce mode: update seed
483    #[allow(dead_code)]
484    const MODE_NO_SEED_UPDATE: u8 = 0x01; // Nonce mode: do not update seed
485    #[allow(dead_code)]
486    const MODE_INVALID: u8 = 0x02; // Nonce mode 2 is invalid.
487    const MODE_PASSTHROUGH: u8 = 0x03; // Nonce mode: pass-through
488    #[allow(dead_code)]
489    const MODE_INPUT_LEN_MASK: u8 = 0x20; // Nonce mode: input size mask
490    #[allow(dead_code)]
491    const MODE_INPUT_LEN_32: u8 = 0x00; // Nonce mode: input size is 32 bytes
492    #[allow(dead_code)]
493    const MODE_INPUT_LEN_64: u8 = 0x20; // Nonce mode: input size is 64 bytes
494    const MODE_TARGET_MASK: u8 = 0xc0; // Nonce mode: target mask
495    #[allow(dead_code)]
496    const MODE_TARGET_TEMPKEY: u8 = 0x00; // Nonce mode: target is TempKey
497    const MODE_TARGET_MSGDIGBUF: u8 = 0x40; // Nonce mode: target is Message Digest Buffer
498    #[allow(dead_code)]
499    const MODE_TARGET_ALTKEYBUF: u8 = 0x80; // Nonce mode: target is Alternate Key Buffer
500
501    pub(crate) fn new(builder: PacketBuilder<'a>) -> Self {
502        let counter = 0x4432;
503        Self { builder, counter }
504    }
505
506    // TODO: Usage of Nonce, especially its correct timing is not clear. In
507    // `test/api_atcab/atca_tests_aes.c`, AES encryption/decryption assumes
508    // nonce value is loaded to TempKey in advance.
509    pub(crate) fn message_digest_buffer(&mut self, msg: &Digest) -> Result<Packet, Error> {
510        let mode = Self::MODE_PASSTHROUGH | (Self::MODE_TARGET_MSGDIGBUF & Self::MODE_TARGET_MASK);
511        let packet = self
512            .builder
513            .opcode(OpCode::Nonce)
514            .mode(mode)
515            .pdu_data(msg)
516            .build()?;
517        Ok(packet)
518    }
519
520    #[allow(dead_code)]
521    fn load(&mut self) -> Self {
522        unimplemented!()
523    }
524
525    #[allow(dead_code)]
526    fn rand(&mut self) -> Self {
527        unimplemented!()
528    }
529
530    #[allow(dead_code)]
531    fn challenge(&mut self) -> Self {
532        unimplemented!()
533    }
534
535    #[allow(dead_code)]
536    fn challenge_seed_update(&mut self) -> Self {
537        unimplemented!()
538    }
539}
540
541/// PrivWrite
542impl<'a> PrivWrite<'a> {
543    pub(crate) fn new(builder: PacketBuilder<'a>) -> Self {
544        Self(builder)
545    }
546
547    pub(crate) fn write_private_key(
548        &mut self,
549        key_id: Slot,
550        private_key: &Block,
551    ) -> Result<Packet, Error> {
552        // Input is an ECC private key consisting of padding 4 bytes of all 0s
553        // and 32 byte integer.
554        let private_key_range = 4..Size::Block.len() + 4;
555        let private_key_length = private_key_range.end;
556        let mac_range = private_key_length..private_key_length + Size::Block.len();
557        let mac_length = mac_range.end;
558        // Write the padding and private key to the PDU buffer directly.
559        self.0.pdu_buffer()[private_key_range]
560            .as_mut()
561            .copy_from_slice(private_key.as_ref());
562        let packet = self
563            .0
564            .pdu_length(mac_length)
565            .opcode(OpCode::PrivWrite)
566            .param2(key_id as u16)
567            .build()?;
568        Ok(packet)
569    }
570}
571
572impl<'a> Sha<'a> {
573    /// Initialization, does not accept a message
574    const MODE_SHA256_START: u8 = 0x00;
575    /// Add 64 bytes in the meesage to the SHA context
576    const MODE_SHA256_UPDATE: u8 = 0x01;
577    /// Complete the calculation and return the digest
578    const MODE_SHA256_END: u8 = 0x02;
579    /// Add 64 byte ECC public key in the slot to the SHA context
580    #[allow(dead_code)]
581    const MODE_SHA256_PUBLIC: u8 = 0x03;
582
583    pub(crate) fn new(builder: PacketBuilder<'a>) -> Self {
584        Self(builder)
585    }
586
587    pub(crate) fn start(&mut self) -> Result<Packet, Error> {
588        let packet = self
589            .0
590            .opcode(OpCode::Sha)
591            .mode(Self::MODE_SHA256_START)
592            .build()?;
593        Ok(packet)
594    }
595
596    /// Data length should be exactly 64 bytes.
597    pub(crate) fn update(&mut self, data: impl AsRef<[u8]>) -> Result<Packet, Error> {
598        let length = data.as_ref().len();
599        if length != 64 {
600            return Err(ErrorKind::BadParam.into());
601        }
602
603        let packet = self
604            .0
605            .opcode(OpCode::Sha)
606            .mode(Self::MODE_SHA256_UPDATE)
607            .param2(length as u16)
608            .pdu_data(data)
609            .build()?;
610        Ok(packet)
611    }
612
613    /// Command execution will return a digest of Block size.
614    pub(crate) fn end(&mut self, data: impl AsRef<[u8]>) -> Result<Packet, Error> {
615        let length = data.as_ref().len();
616        if length > 64 {
617            return Err(ErrorKind::BadParam.into());
618        }
619
620        let packet = self
621            .0
622            .opcode(OpCode::Sha)
623            .mode(Self::MODE_SHA256_END)
624            .param2(length as u16)
625            .pdu_data(data)
626            .build()?;
627        Ok(packet)
628    }
629}
630
631/// AES
632impl<'a> Aes<'a> {
633    pub(crate) const DATA_SIZE: usize = 0x10;
634    /// AES mode: Encrypt
635    const MODE_ENCRYPT: u8 = 0x00;
636    /// AES mode: Decrypt
637    const MODE_DECRYPT: u8 = 0x01;
638
639    pub(crate) fn new(builder: PacketBuilder<'a>) -> Self {
640        Self(builder)
641    }
642
643    /// Plain text has length of 16 bytes.
644    pub(crate) fn encrypt(&mut self, slot: Slot, plaintext: &[u8]) -> Result<Packet, Error> {
645        if !slot.is_private_key() {
646            return Err(ErrorKind::BadParam.into());
647        }
648
649        // Input length should be exactly 16 bytes. Otherwise the device
650        // couldn't recognize the command properly.
651        if plaintext.len() != Self::DATA_SIZE {
652            return Err(ErrorKind::InvalidSize.into());
653        }
654
655        let packet = self
656            .0
657            .opcode(OpCode::Aes)
658            .mode(Self::MODE_ENCRYPT)
659            .param2(slot as u16)
660            .pdu_data(plaintext)
661            .build()?;
662        Ok(packet)
663    }
664
665    /// Cipher text has length of 16 bytes.
666    pub(crate) fn decrypt(&mut self, slot: Slot, ciphertext: &[u8]) -> Result<Packet, Error> {
667        if !slot.is_private_key() {
668            return Err(ErrorKind::BadParam.into());
669        }
670
671        // Input length should be exactly 16 bytes. Otherwise the device
672        // couldn't recognize the command properly.
673        if ciphertext.len() != Self::DATA_SIZE {
674            return Err(ErrorKind::InvalidSize.into());
675        }
676
677        let packet = self
678            .0
679            .opcode(OpCode::Aes)
680            .mode(Self::MODE_DECRYPT)
681            .param2(slot as u16)
682            .pdu_data(ciphertext)
683            .build()?;
684        Ok(packet)
685    }
686}
687
688/// Random
689impl<'a> Random<'a> {
690    const MODE_SEED_UPDATE: u8 = 0x00;
691
692    pub(crate) fn new(builder: PacketBuilder<'a>) -> Self {
693        Self(builder)
694    }
695
696    pub(crate) fn random(&mut self) -> Result<Packet, Error> {
697        let packet = self
698            .0
699            .opcode(OpCode::Random)
700            .mode(Self::MODE_SEED_UPDATE)
701            .build()?;
702        Ok(packet)
703    }
704}
705
706/// Read
707impl<'a> Read<'a> {
708    pub(crate) fn new(builder: PacketBuilder<'a>) -> Self {
709        Self(builder)
710    }
711
712    pub(crate) fn slot(&mut self, slot: Slot, block: u8) -> Result<Packet, Error> {
713        let addr = Zone::Data.get_slot_addr(slot, block)?;
714        let mode = Zone::Data.encode(Size::Block);
715        let packet = self
716            .0
717            .opcode(OpCode::Read)
718            .mode(mode)
719            .param2(addr)
720            .build()?;
721        Ok(packet)
722    }
723
724    pub(crate) fn read(
725        &mut self,
726        zone: Zone,
727        size: Size,
728        block: u8,
729        offset: u8,
730    ) -> Result<Packet, Error> {
731        let addr = zone.get_addr(block, offset)?;
732        let mode = zone.encode(size);
733        let packet = self
734            .0
735            .opcode(OpCode::Read)
736            .mode(mode)
737            .param2(addr)
738            .build()?;
739        Ok(packet)
740    }
741}
742
743/// Sign
744impl<'a> Sign<'a> {
745    const MODE_SOURCE_MSGDIGBUF: u8 = 0x20;
746    const MODE_EXTERNAL: u8 = 0x80;
747
748    pub(crate) fn new(builder: PacketBuilder<'a>) -> Self {
749        Self(builder)
750    }
751
752    // Sign a 32-byte external message using the private key in the specified
753    // slot.
754    pub(crate) fn external(&mut self, key_id: Slot) -> Result<Packet, Error> {
755        let mode = Self::MODE_EXTERNAL | Self::MODE_SOURCE_MSGDIGBUF;
756        let packet = self
757            .0
758            .opcode(OpCode::Sign)
759            .mode(mode)
760            .param2(key_id as u16)
761            .build()?;
762        Ok(packet)
763    }
764}
765
766/// Verify
767impl<'a> Verify<'a> {
768    const MODE_SOURCE_MSGDIGBUF: u8 = 0x20;
769    const MODE_EXTERNAL: u8 = 0x02;
770    const KEY_P256: u16 = 0x0004;
771
772    pub(crate) fn new(builder: PacketBuilder<'a>) -> Self {
773        Self(builder)
774    }
775
776    // Verify a 32-byte external message using the private key in the specified
777    // slot.
778    pub(crate) fn external(
779        &mut self,
780        signature: &Signature,
781        public_key: &PublicKey,
782    ) -> Result<Packet, Error> {
783        let mode = Self::MODE_EXTERNAL | Self::MODE_SOURCE_MSGDIGBUF;
784
785        // Load PDU data
786        let sig_length = signature.as_ref().len();
787        let (sig_buf, pdu_buffer) = self.0.pdu_buffer().split_at_mut(sig_length);
788        sig_buf.copy_from_slice(signature.as_ref());
789        let pubkey_length = public_key.as_ref().len();
790        let (pubkey_buffer, _) = pdu_buffer.split_at_mut(pubkey_length);
791        pubkey_buffer.copy_from_slice(public_key.as_ref());
792
793        let packet = self
794            .0
795            .opcode(OpCode::Verify)
796            .mode(mode)
797            .param2(Self::KEY_P256)
798            .pdu_length(sig_length + pubkey_length)
799            .build()?;
800        Ok(packet)
801    }
802}
803
804/// Write
805impl<'a> Write<'a> {
806    pub(crate) fn new(builder: PacketBuilder<'a>) -> Self {
807        Self(builder)
808    }
809
810    pub(crate) fn slot(&mut self, slot: Slot, block: u8, data: &Block) -> Result<Packet, Error> {
811        let addr = Zone::Data.get_slot_addr(slot, block)?;
812        let mode = Zone::Data.encode(Size::Block);
813        let packet = self
814            .0
815            .opcode(OpCode::Write)
816            .mode(mode)
817            .param2(addr)
818            .pdu_data(data)
819            .build()?;
820        Ok(packet)
821    }
822
823    pub(crate) fn write(
824        &mut self,
825        zone: Zone,
826        size: Size,
827        block: u8,
828        offset: u8,
829        data: impl AsRef<[u8]>,
830    ) -> Result<Packet, Error> {
831        if size.len() != data.as_ref().len() {
832            return Err(ErrorKind::BadParam.into());
833        }
834
835        let addr = zone.get_addr(block, offset)?;
836        let mode = zone.encode(size);
837        let packet = self
838            .0
839            .opcode(OpCode::Write)
840            .mode(mode)
841            .param2(addr)
842            .pdu_data(data)
843            .build()?;
844        Ok(packet)
845    }
846}
847
848#[cfg(test)]
849mod tests {
850    use super::*;
851
852    #[test]
853    fn sha() {
854        let buf = &mut [0x00u8; 0xff];
855        let packet = Sha::new(PacketBuilder::new(buf.as_mut()))
856            .start()
857            .unwrap()
858            .buffer(buf.as_ref());
859        assert_eq!(packet[0x01], 0x07);
860        assert_eq!(packet[0x02], OpCode::Sha as u8);
861        assert_eq!(packet[0x03], Sha::MODE_SHA256_START);
862        assert_eq!(packet[0x04..0x06], [0x00, 0x00]);
863    }
864
865    #[test]
866    fn lock() {
867        let buf = &mut [0x00u8; 0xff];
868        let packet = Lock::new(PacketBuilder::new(buf.as_mut()))
869            .zone(Zone::Config, None)
870            .unwrap()
871            .buffer(buf.as_ref());
872        assert_eq!(packet[0x01], 0x07);
873        assert_eq!(packet[0x02], OpCode::Lock as u8);
874        assert_eq!(packet[0x03], 0x80);
875        assert_eq!(packet[0x04..0x06], [0x00, 0x00]);
876    }
877
878    #[test]
879    fn lock_crc() {
880        let buf = &mut [0x00u8; 0xff];
881        let crc = 0xDEAD;
882        let packet = Lock::new(PacketBuilder::new(buf.as_mut()))
883            .zone(Zone::Config, Some(crc))
884            .unwrap()
885            .buffer(buf.as_ref());
886        assert_eq!(packet[0x01], 0x07);
887        assert_eq!(packet[0x02], OpCode::Lock as u8);
888        assert_eq!(packet[0x03], 0x00);
889        assert_eq!(packet[0x04..0x06], crc.to_le_bytes());
890    }
891
892    #[test]
893    fn genkey() {
894        let buf = &mut [0x00u8; 0xff];
895        let packet = GenKey::new(PacketBuilder::new(buf.as_mut()))
896            .private_key(Slot::PrivateKey01)
897            .unwrap()
898            .buffer(buf.as_ref());
899        assert_eq!(packet[0x01], 0x07);
900        assert_eq!(packet[0x02], OpCode::GenKey as u8);
901        assert_eq!(packet[0x03], 0x04);
902        assert_eq!(packet[0x04..0x06], [0x01, 0x00]);
903    }
904
905    #[test]
906    fn privwrite() {
907        let buf = &mut [0x00u8; 0xff];
908        let mut data = Block::default();
909        data.as_mut()
910            .iter_mut()
911            .enumerate()
912            .for_each(|(i, v)| *v = i as u8);
913        let packet = PrivWrite::new(PacketBuilder::new(buf.as_mut()))
914            .write_private_key(Slot::PrivateKey01, &data)
915            .unwrap()
916            .buffer(buf.as_ref());
917        assert_eq!(packet[0x01], 0x4b);
918        assert_eq!(packet[0x02], OpCode::PrivWrite as u8);
919        assert_eq!(packet[0x03], 0x00);
920        assert_eq!(packet[0x04..0x06], [0x01, 0x00]);
921        assert_eq!(packet[0x06..0x0a], [0x00; 0x04]);
922        assert_eq!(packet[0x0a..0x2a].as_ref(), data.as_ref());
923    }
924
925    #[test]
926    fn verify() {
927        let buf = &mut [0x00u8; 0xff];
928        let mut signature = Signature::default();
929        let mut public_key = PublicKey::default();
930
931        let (r, s) = signature.as_mut().split_at_mut(32);
932        r.iter_mut().for_each(|v| *v = 'r' as u8);
933        s.iter_mut().for_each(|v| *v = 's' as u8);
934        let (x, y) = public_key.as_mut().split_at_mut(32);
935        x.iter_mut().for_each(|v| *v = 'x' as u8);
936        y.iter_mut().for_each(|v| *v = 'y' as u8);
937
938        let packet = Verify::new(PacketBuilder::new(buf.as_mut()))
939            .external(&signature, &public_key)
940            .unwrap()
941            .buffer(buf.as_ref());
942        assert_eq!(packet[0x01], 0x87);
943        assert_eq!(packet[0x02], OpCode::Verify as u8);
944        assert_eq!(packet[0x03], 0x22);
945        assert_eq!(packet[0x04..0x06], [0x04, 0x00]);
946        assert_eq!(packet[0x06..0x46].as_ref(), signature.as_ref());
947        assert_eq!(packet[0x46..0x86].as_ref(), public_key.as_ref());
948    }
949}