1use std::cell::RefCell;
2use std::cmp::min;
3use std::collections::HashMap;
4use std::convert::{From, TryFrom};
5use std::mem::discriminant;
6use std::ptr;
7use std::sync::Mutex;
8
9#[cfg(test)]
10use cryptoauthlib_sys::atca_aes_cbc_ctx_t;
11#[cfg(test)]
12use cryptoauthlib_sys::atca_aes_ctr_ctx_t;
13
14use super::{
15 AeadAlgorithm, AeadParam, AtcaAesCcmCtx, AtcaDeviceType, AtcaIfaceCfg, AtcaIfaceCfgPtrWrapper,
16 AtcaIfaceType, AtcaSlot, AtcaSlotCapacity, AtcaStatus, AteccDeviceTrait, ChipOptions,
17 CipherAlgorithm, CipherOperation, CipherParam, EccKeyAttr, EcdhParams, EcdhResult, EcdhSource,
18 EcdhTarget, FeedbackMode, HkdfMsgLoc, InfoCmdType, KdfAlgorithm, KdfParams, KdfPrfKeyLen,
19 KdfPrfTargetLen, KdfResult, KdfSource, KdfTarget, KeyType, MacAlgorithm, MacParam, NonceTarget,
20 OutputProtectionState, ReadKey, SignMode, SlotConfig, VerifyMode, WriteConfig,
21};
22use super::{
23 ATCA_AES_DATA_SIZE, ATCA_AES_GCM_IV_STD_LENGTH, ATCA_AES_KEY_SIZE,
24 ATCA_ATECC_CONFIG_BUFFER_SIZE, ATCA_ATECC_MIN_SLOT_IDX_FOR_PUB_KEY, ATCA_ATECC_PRIV_KEY_SIZE,
25 ATCA_ATECC_PUB_KEY_SIZE, ATCA_ATECC_SLOTS_COUNT, ATCA_ATECC_TEMPKEY_KEYID,
26 ATCA_ATSHA_CONFIG_BUFFER_SIZE, ATCA_BLOCK_SIZE, ATCA_ECDH_KEY_SIZE, ATCA_KDF_MAX_MSG_SIZE,
27 ATCA_KEY_SIZE, ATCA_LOCK_ZONE_CONFIG, ATCA_LOCK_ZONE_DATA, ATCA_NONCE_NUMIN_SIZE,
28 ATCA_NONCE_SIZE, ATCA_RANDOM_BUFFER_SIZE, ATCA_SERIAL_NUM_SIZE, ATCA_SHA2_256_DIGEST_SIZE,
29 ATCA_SIG_SIZE, ATCA_ZONE_DATA, SHA_MODE_TARGET_TEMPKEY,
30};
31
32mod aes_ccm;
33mod aes_cipher;
34mod aes_gcm;
35mod c2rust;
36mod ecdh;
37mod kdf;
38mod mac;
39mod provisioning;
40mod rust2c;
41
42struct AteccResourceManager {
43 ref_counter: u8,
44}
45
46lazy_static! {
47 static ref ATECC_RESOURCE_MANAGER: Mutex<AteccResourceManager> =
48 Mutex::new(AteccResourceManager { ref_counter: 0 });
49}
50
51impl AteccResourceManager {
52 fn acquire(&mut self) -> bool {
54 if self.ref_counter == 0 {
55 self.ref_counter = 1;
56 true
57 } else {
58 false
59 }
60 }
61
62 fn release(&mut self) -> bool {
64 if self.ref_counter == 1 {
65 self.ref_counter = 0;
66 true
67 } else {
68 false
69 }
70 }
71}
72
73#[derive(Debug)]
75pub struct AteccDevice {
76 iface_cfg_ptr: AtcaIfaceCfgPtrWrapper,
79 api_mutex: Mutex<()>,
81 serial_number: [u8; ATCA_SERIAL_NUM_SIZE],
82 config_zone_locked: bool,
83 data_zone_locked: bool,
84 chip_options: ChipOptions,
85 access_keys: Mutex<RefCell<HashMap<u8, [u8; ATCA_KEY_SIZE]>>>,
86 slots: Vec<AtcaSlot>,
87}
88
89impl Default for AteccDevice {
90 fn default() -> AteccDevice {
91 AteccDevice {
92 iface_cfg_ptr: AtcaIfaceCfgPtrWrapper {
93 ptr: std::ptr::null_mut(),
94 },
95 api_mutex: Mutex::new(()),
96 serial_number: [0; ATCA_SERIAL_NUM_SIZE],
97 config_zone_locked: false,
98 data_zone_locked: false,
99 chip_options: Default::default(),
100 access_keys: Mutex::new(RefCell::new(HashMap::new())),
101 slots: Vec::new(),
102 }
103 }
104}
105
106impl AteccDeviceTrait for AteccDevice {
107 fn random(&self, rand_out: &mut Vec<u8>) -> AtcaStatus {
110 self.random(rand_out)
111 } fn sha(&self, message: Vec<u8>, digest: &mut Vec<u8>) -> AtcaStatus {
116 self.sha(message, digest)
117 } fn nonce(&self, target: NonceTarget, data: &[u8]) -> AtcaStatus {
126 self.nonce(target, data)
127 } fn nonce_rand(&self, host_nonce: &[u8], rand_out: &mut Vec<u8>) -> AtcaStatus {
133 self.nonce_rand(host_nonce, rand_out)
134 } fn gen_key(&self, key_type: KeyType, slot_id: u8) -> AtcaStatus {
139 self.gen_key(key_type, slot_id)
140 } fn import_key(&self, key_type: KeyType, key_data: &[u8], slot_id: u8) -> AtcaStatus {
145 self.import_key(key_type, key_data, slot_id)
146 } fn export_key(&self, key_type: KeyType, key_data: &mut Vec<u8>, slot_id: u8) -> AtcaStatus {
151 self.export_key(key_type, key_data, slot_id)
152 } fn get_public_key(&self, slot_id: u8, public_key: &mut Vec<u8>) -> AtcaStatus {
159 self.get_public_key(slot_id, public_key)
160 } fn sign_hash(&self, mode: SignMode, slot_id: u8, signature: &mut Vec<u8>) -> AtcaStatus {
165 self.sign_hash(mode, slot_id, signature)
166 } fn verify_hash(
171 &self,
172 mode: VerifyMode,
173 hash: &[u8],
174 signature: &[u8],
175 ) -> Result<bool, AtcaStatus> {
176 self.verify_hash(mode, hash, signature)
177 } fn cipher_encrypt(
182 &self,
183 algorithm: CipherAlgorithm,
184 slot_id: u8,
185 data: &mut Vec<u8>,
186 ) -> AtcaStatus {
187 self.cipher_encrypt(algorithm, slot_id, data)
188 } fn cipher_decrypt(
193 &self,
194 algorithm: CipherAlgorithm,
195 slot_id: u8,
196 data: &mut Vec<u8>,
197 ) -> AtcaStatus {
198 self.cipher_decrypt(algorithm, slot_id, data)
199 } fn aead_encrypt(
204 &self,
205 algorithm: AeadAlgorithm,
206 slot_id: u8,
207 data: &mut Vec<u8>,
208 ) -> Result<Vec<u8>, AtcaStatus> {
209 self.aead_encrypt(algorithm, slot_id, data)
210 } fn aead_decrypt(
215 &self,
216 algorithm: AeadAlgorithm,
217 slot_id: u8,
218 data: &mut Vec<u8>,
219 ) -> Result<bool, AtcaStatus> {
220 self.aead_decrypt(algorithm, slot_id, data)
221 } fn mac_compute(
226 &self,
227 algorithm: MacAlgorithm,
228 slot_id: u8,
229 data: &[u8],
230 ) -> Result<Vec<u8>, AtcaStatus> {
231 self.mac_compute(algorithm, slot_id, data)
232 } fn mac_verify(
237 &self,
238 algorithm: MacAlgorithm,
239 slot_id: u8,
240 data: &[u8],
241 ) -> Result<bool, AtcaStatus> {
242 self.mac_verify(algorithm, slot_id, data)
243 } fn kdf(
249 &self,
250 algorithm: KdfAlgorithm,
251 parameters: KdfParams,
252 message: Option<&[u8]>,
253 message_length: usize,
254 ) -> Result<KdfResult, AtcaStatus> {
255 self.kdf(algorithm, parameters, message, message_length)
256 } fn ecdh(
261 &self,
262 parameters: EcdhParams,
263 peer_public_key: &[u8],
264 ) -> Result<EcdhResult, AtcaStatus> {
265 self.ecdh(parameters, peer_public_key)
266 } fn lock_config_zone(&self) -> AtcaStatus {
272 self.lock_config_zone()
273 } fn lock_data_zone(&self) -> AtcaStatus {
279 self.lock_data_zone()
280 } fn lock_slot(&self, slot_id: u8) -> AtcaStatus {
287 self.lock_slot(slot_id)
288 } fn load_config_into_chip(&self, config: &[u8]) -> AtcaStatus {
296 self.load_config_into_chip(config)
297 } fn get_device_type(&self) -> AtcaDeviceType {
302 self.get_device_type()
303 } fn is_configuration_locked(&self) -> bool {
309 self.config_zone_locked
310 } fn is_data_zone_locked(&self) -> bool {
316 self.data_zone_locked
317 } fn get_config(&self, atca_slots: &mut Vec<AtcaSlot>) -> AtcaStatus {
323 self.get_config(atca_slots)
324 } fn info_cmd(&self, command: InfoCmdType) -> Result<Vec<u8>, AtcaStatus> {
329 self.info_cmd(command)
330 } fn add_access_key(&self, slot_id: u8, access_key: &[u8]) -> AtcaStatus {
337 self.add_access_key(slot_id, access_key)
338 } fn flush_access_keys(&self) -> AtcaStatus {
344 self.flush_access_keys()
345 } fn get_serial_number(&self) -> [u8; ATCA_SERIAL_NUM_SIZE] {
350 self.serial_number
351 } fn is_aes_enabled(&self) -> bool {
357 self.chip_options.aes_enabled
358 } fn is_kdf_aes_enabled(&self) -> bool {
364 self.chip_options.kdf_aes_enabled
365 } fn is_kdf_iv_enabled(&self) -> bool {
371 self.chip_options.kdf_iv_enabled
372 } fn is_io_protection_key_enabled(&self) -> bool {
378 self.chip_options.io_key_enabled
379 } fn get_ecdh_output_protection_state(&self) -> OutputProtectionState {
385 self.chip_options.ecdh_output_protection
386 } fn get_kdf_output_protection_state(&self) -> OutputProtectionState {
392 self.chip_options.kdf_output_protection
393 } fn wakeup(&self) -> AtcaStatus {
398 self.wakeup()
399 } fn sleep(&self) -> AtcaStatus {
404 self.sleep()
405 } fn release(&self) -> AtcaStatus {
410 self.release()
411 } #[cfg(test)]
422 fn read_zone(&self, zone: u8, slot: u16, block: u8, offset: u8, data: &mut [u8]) -> AtcaStatus {
423 self.read_zone(zone, slot, block, offset, data)
424 } #[cfg(test)]
431 fn read_config_zone(&self, config_data: &mut Vec<u8>) -> AtcaStatus {
432 self.read_config_zone(config_data)
433 } #[cfg(test)]
439 fn cmp_config_zone(&self, config_data: &mut [u8]) -> Result<bool, AtcaStatus> {
440 self.cmp_config_zone(config_data)
441 } #[cfg(test)]
448 fn get_access_key(&self, slot_id: u8, key: &mut Vec<u8>) -> AtcaStatus {
449 self.get_access_key(slot_id, key)
450 } #[cfg(test)]
455 fn aes_encrypt_block(
456 &self,
457 key_id: u16,
458 key_block: u8,
459 input: &[u8],
460 ) -> Result<[u8; ATCA_AES_DATA_SIZE], AtcaStatus> {
461 self.aes_encrypt_block(key_id, key_block, input)
462 } #[cfg(test)]
467 fn aes_decrypt_block(
468 &self,
469 key_id: u16,
470 key_block: u8,
471 input: &[u8],
472 ) -> Result<[u8; ATCA_AES_DATA_SIZE], AtcaStatus> {
473 self.aes_decrypt_block(key_id, key_block, input)
474 } #[cfg(test)]
479 fn aes_ctr_init(
480 &self,
481 slot_id: u8,
482 counter_size: u8,
483 iv: &[u8],
484 ) -> Result<atca_aes_ctr_ctx_t, AtcaStatus> {
485 self.aes_ctr_init(slot_id, counter_size, iv)
486 } #[cfg(test)]
491 fn aes_ctr_increment(&self, ctx: atca_aes_ctr_ctx_t) -> Result<atca_aes_ctr_ctx_t, AtcaStatus> {
492 self.aes_ctr_increment(ctx)
493 } #[cfg(test)]
498 fn aes_cbc_init(&self, slot_id: u8, iv: &[u8]) -> Result<atca_aes_cbc_ctx_t, AtcaStatus> {
499 self.aes_cbc_init(slot_id, iv)
500 } #[cfg(test)]
506 fn get_slot_capacity(&self, slot_id: u8) -> AtcaSlotCapacity {
507 self.get_slot_capacity(slot_id)
508 } }
510
511impl AteccDevice {
513 pub fn new(r_iface_cfg: AtcaIfaceCfg) -> Result<AteccDevice, String> {
515 if !ATECC_RESOURCE_MANAGER.lock().unwrap().acquire() {
516 return Err(AtcaStatus::AtcaAllocFailure.to_string());
517 }
518 let iface_cfg = Box::new(
519 match cryptoauthlib_sys::ATCAIfaceCfg::try_from(r_iface_cfg) {
520 Ok(x) => x,
521 Err(()) => {
522 ATECC_RESOURCE_MANAGER.lock().unwrap().release();
523 return Err(AtcaStatus::AtcaBadParam.to_string());
524 }
525 },
526 );
527 let mut atecc_device = AteccDevice::default();
528
529 let iface_cfg_raw_ptr: *mut cryptoauthlib_sys::ATCAIfaceCfg = Box::into_raw(iface_cfg);
530 let result = AtcaStatus::from(unsafe {
534 let _guard = atecc_device
535 .api_mutex
536 .lock()
537 .expect("Could not lock atcab API mutex");
538 cryptoauthlib_sys::atcab_init(iface_cfg_raw_ptr)
539 });
540
541 atecc_device.iface_cfg_ptr = match result {
542 AtcaStatus::AtcaSuccess => AtcaIfaceCfgPtrWrapper {
543 ptr: iface_cfg_raw_ptr,
544 },
545 _ => {
546 ATECC_RESOURCE_MANAGER.lock().unwrap().release();
548 unsafe { Box::from_raw(iface_cfg_raw_ptr) };
549 return Err(result.to_string());
550 }
551 };
552
553 let mut config_data = Vec::new();
557 let result = atecc_device.get_config_from_chip(&mut config_data);
558 if result != AtcaStatus::AtcaSuccess {
559 atecc_device.release();
560 return Err(result.to_string());
561 }
562
563 atecc_device.serial_number = atecc_device.get_serial_number(&config_data);
564
565 atecc_device.slots = {
566 let mut atca_slots = Vec::new();
567 atcab_get_slots_config_from_config_data(&config_data, &mut atca_slots);
568 atca_slots
569 };
570
571 atecc_device.config_zone_locked =
572 atecc_device.is_locked(&config_data, ATCA_LOCK_ZONE_CONFIG);
573
574 atecc_device.data_zone_locked = atecc_device.is_locked(&config_data, ATCA_LOCK_ZONE_DATA);
575
576 atecc_device.get_chip_options_data_from_chip_config_data(&config_data);
577
578 let chip_type = atecc_device.get_device_type();
579 let err_str = "\n\n\u{001b}[1m\u{001b}[33mcheck if 'device_type' is correct in \
580 'config.toml' file, because chip on the bus seems to be";
581 if atecc_device.chip_options.aes_enabled && (chip_type != AtcaDeviceType::ATECC608A) {
582 atecc_device.release();
583 return Err(format!(
584 "{} type ATECC608x,\nand you have chosen \u{001b}[31m{}\u{001b}[33m !\u{001b}[0m\n\n",
585 err_str,
586 chip_type
587 ));
588 }
589 if !atecc_device.chip_options.aes_enabled && (chip_type == AtcaDeviceType::ATECC608A) {
590 atecc_device.release();
591 return Err(format!(
592 "{} of a different type than the \u{001b}[31mATECC608x\u{001b}[33m you selected !\u{001b}[0m\n\n",
593 err_str
594 ));
595 }
596
597 Ok(atecc_device)
598 } fn random(&self, rand_out: &mut Vec<u8>) -> AtcaStatus {
602 if self.check_that_configuration_is_not_locked(false) {
603 return AtcaStatus::AtcaNotLocked;
604 }
605 rand_out.resize(ATCA_RANDOM_BUFFER_SIZE, 0);
606 AtcaStatus::from(unsafe {
607 let _guard = self
608 .api_mutex
609 .lock()
610 .expect("Could not lock atcab API mutex");
611 cryptoauthlib_sys::atcab_random(rand_out.as_mut_ptr())
612 })
613 } fn sha(&self, message: Vec<u8>, digest: &mut Vec<u8>) -> AtcaStatus {
617 if self.check_that_configuration_is_not_locked(false) {
618 return AtcaStatus::AtcaNotLocked;
619 }
620 let length: u16 = match u16::try_from(message.len()) {
621 Ok(val) => val,
622 Err(_) => return AtcaStatus::AtcaBadParam,
623 };
624
625 digest.resize(ATCA_SHA2_256_DIGEST_SIZE, 0);
626
627 AtcaStatus::from(unsafe {
628 let _guard = self
629 .api_mutex
630 .lock()
631 .expect("Could not lock atcab API mutex");
632 cryptoauthlib_sys::atcab_sha(length, message.as_ptr(), digest.as_mut_ptr())
633 })
634 } fn nonce(&self, target: NonceTarget, data: &[u8]) -> AtcaStatus {
642 if (self.get_device_type() != AtcaDeviceType::ATECC608A) && (target != NonceTarget::TempKey)
643 {
644 return AtcaStatus::AtcaBadParam;
645 }
646 let dev_type_608: bool = AtcaDeviceType::ATECC608A == self.get_device_type();
647 let alt_key_buff: bool = NonceTarget::AltKeyBuf == target;
648 let no_len_32: bool = data.len() != ATCA_NONCE_SIZE;
649 let no_len_64: bool = data.len() != (2 * ATCA_NONCE_SIZE);
650
651 if !dev_type_608 && alt_key_buff
652 || alt_key_buff && no_len_32
653 || !dev_type_608 && !no_len_64
654 || no_len_32 && no_len_64
655 || !no_len_32 && !no_len_64
656 {
657 return AtcaStatus::AtcaInvalidSize;
658 }
659 AtcaStatus::from(unsafe {
660 let _guard = self
661 .api_mutex
662 .lock()
663 .expect("Could not lock atcab API mutex");
664 cryptoauthlib_sys::atcab_nonce_load(target as u8, data.as_ptr(), data.len() as u16)
665 })
666 } fn nonce_rand(&self, host_nonce: &[u8], rand_out: &mut Vec<u8>) -> AtcaStatus {
671 if host_nonce.len() != ATCA_NONCE_NUMIN_SIZE {
672 return AtcaStatus::AtcaInvalidSize;
673 }
674
675 rand_out.resize(ATCA_RANDOM_BUFFER_SIZE, 0);
676
677 AtcaStatus::from(unsafe {
678 let _guard = self
679 .api_mutex
680 .lock()
681 .expect("Could not lock atcab API mutex");
682 cryptoauthlib_sys::atcab_nonce_rand(host_nonce.as_ptr(), rand_out.as_mut_ptr())
683 })
684 } fn gen_key(&self, key_type: KeyType, slot_id: u8) -> AtcaStatus {
688 if self.check_that_configuration_is_not_locked(false) {
689 return AtcaStatus::AtcaNotLocked;
690 }
691
692 if let Err(err) = self.encryption_key_setup_parameters_check(key_type, slot_id) {
693 return err;
694 }
695
696 let slot = match slot_id {
697 ATCA_ATECC_SLOTS_COUNT => ATCA_ATECC_TEMPKEY_KEYID,
698 _ => slot_id as u16,
699 };
700
701 match key_type {
702 KeyType::P256EccKey => {
703 if (slot_id < ATCA_ATECC_SLOTS_COUNT)
704 && !self.slots[slot_id as usize].config.is_secret
705 {
706 return AtcaStatus::AtcaBadParam;
707 }
708 AtcaStatus::from(unsafe {
709 let _guard = self
710 .api_mutex
711 .lock()
712 .expect("Could not lock atcab API mutex");
713 cryptoauthlib_sys::atcab_genkey(slot, ptr::null_mut() as *mut u8)
714 })
715 }
716 KeyType::Aes => {
717 const BLOCK_IDX: u8 = 0;
718
719 let mut key: Vec<u8> = Vec::with_capacity(ATCA_RANDOM_BUFFER_SIZE);
720 let result = self.random(&mut key);
721 if AtcaStatus::AtcaSuccess != result {
722 return result;
723 }
724
725 for idx in &mut key[ATCA_AES_KEY_SIZE..] {
726 *idx = 0x00
727 }
728
729 match slot {
730 ATCA_ATECC_TEMPKEY_KEYID => AtcaStatus::AtcaUnimplemented, _ => self.write_slot(slot, BLOCK_IDX, &key),
732 }
733 }
734 _ => AtcaStatus::AtcaBadParam,
735 }
736 } fn import_key(&self, key_type: KeyType, key_data: &[u8], slot_id: u8) -> AtcaStatus {
740 if self.check_that_configuration_is_not_locked(true) {
741 return AtcaStatus::AtcaNotLocked;
742 }
743 if let Err(err) = self.encryption_key_setup_parameters_check(key_type, slot_id) {
744 return err;
745 }
746
747 let slot = match slot_id {
748 ATCA_ATECC_SLOTS_COUNT => ATCA_ATECC_TEMPKEY_KEYID,
749 _ => slot_id as u16,
750 };
751
752 match key_type {
753 KeyType::P256EccKey => self.write_p256_ecc_key_to_slot(key_data, slot),
754 KeyType::Aes => self.write_aes_key_to_slot(key_data, slot),
755 KeyType::ShaOrText => self.write_sha_or_text_key_to_slot(key_data, slot),
756 _ => AtcaStatus::AtcaBadParam,
757 }
758 } fn export_key(&self, key_type: KeyType, key_data: &mut Vec<u8>, slot_id: u8) -> AtcaStatus {
766 if self.check_that_configuration_is_not_locked(true) {
767 return AtcaStatus::AtcaNotLocked;
768 }
769 if slot_id > ATCA_ATECC_SLOTS_COUNT {
770 return AtcaStatus::AtcaInvalidId;
771 };
772 match key_type {
773 KeyType::P256EccKey => self.get_public_key(slot_id, key_data),
774 KeyType::Aes => self.read_aes_key_from_slot(slot_id, key_data),
775 KeyType::ShaOrText => self.read_sha_or_text_key_from_slot(slot_id, key_data),
776 _ => AtcaStatus::AtcaBadParam,
777 }
778 } fn get_public_key(&self, slot_id: u8, public_key: &mut Vec<u8>) -> AtcaStatus {
784 if self.check_that_configuration_is_not_locked(true) {
785 return AtcaStatus::AtcaNotLocked;
786 }
787
788 public_key.resize(ATCA_ATECC_PUB_KEY_SIZE, 0);
789
790 if slot_id == ATCA_ATECC_SLOTS_COUNT {
791 return AtcaStatus::from(unsafe {
792 let _guard = self
793 .api_mutex
794 .lock()
795 .expect("Could not lock atcab API mutex");
796 cryptoauthlib_sys::atcab_get_pubkey(
797 ATCA_ATECC_TEMPKEY_KEYID,
798 public_key.as_mut_ptr(),
799 )
800 });
801 }
802
803 if self.slots[slot_id as usize].config.key_type != KeyType::P256EccKey {
804 return AtcaStatus::AtcaBadParam;
805 }
806
807 if self.slots[slot_id as usize].config.is_secret {
808 if self.slots[slot_id as usize].config.pub_info
809 && self.slots[slot_id as usize].config.ecc_key_attr.is_private
810 {
811 AtcaStatus::from(unsafe {
812 let _guard = self
813 .api_mutex
814 .lock()
815 .expect("Could not lock atcab API mutex");
816 cryptoauthlib_sys::atcab_get_pubkey(slot_id as u16, public_key.as_mut_ptr())
817 })
818 } else if self.slots[slot_id as usize].config.read_key.encrypt_read {
819 if slot_id < ATCA_ATECC_MIN_SLOT_IDX_FOR_PUB_KEY {
820 AtcaStatus::AtcaInvalidId
821 } else {
822 AtcaStatus::AtcaUnimplemented
826 }
827 } else {
828 AtcaStatus::AtcaBadParam
829 }
830 } else if self.slots[slot_id as usize].config.write_config == WriteConfig::Always {
831 if slot_id < ATCA_ATECC_MIN_SLOT_IDX_FOR_PUB_KEY {
832 AtcaStatus::AtcaInvalidId
833 } else {
834 AtcaStatus::from(unsafe {
835 let _guard = self
836 .api_mutex
837 .lock()
838 .expect("Could not lock atcab API mutex");
839 cryptoauthlib_sys::atcab_read_pubkey(slot_id as u16, public_key.as_mut_ptr())
840 })
841 }
842 } else {
843 AtcaStatus::AtcaBadParam
844 }
845 } fn sign_hash(&self, mode: SignMode, slot_id: u8, signature: &mut Vec<u8>) -> AtcaStatus {
849 if self.check_that_configuration_is_not_locked(true) {
850 return AtcaStatus::AtcaNotLocked;
851 }
852 if slot_id >= ATCA_ATECC_SLOTS_COUNT {
853 return AtcaStatus::AtcaInvalidId;
854 }
855 signature.resize(ATCA_SIG_SIZE, 0);
856 match mode {
857 SignMode::External(hash) => AtcaStatus::from(unsafe {
862 let _guard = self
863 .api_mutex
864 .lock()
865 .expect("Could not lock atcab API mutex");
866 cryptoauthlib_sys::atcab_sign(slot_id as u16, hash.as_ptr(), signature.as_mut_ptr())
867 }),
868 _ => AtcaStatus::AtcaUnimplemented,
869 }
870 } fn verify_hash(
874 &self,
875 mode: VerifyMode,
876 hash: &[u8],
877 signature: &[u8],
878 ) -> Result<bool, AtcaStatus> {
879 if self.check_that_configuration_is_not_locked(true) {
880 return Err(AtcaStatus::AtcaNotLocked);
881 }
882 if (signature.len() != ATCA_SIG_SIZE) || (hash.len() != ATCA_SHA2_256_DIGEST_SIZE) {
883 return Err(AtcaStatus::AtcaInvalidSize);
884 };
885 let mut is_verified: bool = false;
886 let result: AtcaStatus;
887
888 match mode {
889 VerifyMode::Internal(slot_number) => {
894 if slot_number >= ATCA_ATECC_SLOTS_COUNT {
895 return Err(AtcaStatus::AtcaInvalidId);
896 }
897 result = AtcaStatus::from(unsafe {
898 let _guard = self
899 .api_mutex
900 .lock()
901 .expect("Could not lock atcab API mutex");
902 cryptoauthlib_sys::atcab_verify_stored(
903 hash.as_ptr(),
904 signature.as_ptr(),
905 slot_number as u16,
906 &mut is_verified,
907 )
908 })
909 }
910 VerifyMode::External(public_key) => {
916 if public_key.len() != ATCA_ATECC_PUB_KEY_SIZE {
917 return Err(AtcaStatus::AtcaInvalidId);
918 }
919 result = AtcaStatus::from(unsafe {
920 let _guard = self
921 .api_mutex
922 .lock()
923 .expect("Could not lock atcab API mutex");
924 cryptoauthlib_sys::atcab_verify_extern(
925 hash.as_ptr(),
926 signature.as_ptr(),
927 public_key.as_ptr(),
928 &mut is_verified,
929 )
930 })
931 }
932 _ => return Err(AtcaStatus::AtcaUnimplemented),
933 }
934
935 match result {
936 AtcaStatus::AtcaSuccess => Ok(is_verified),
937 _ => Err(result),
938 }
939 } fn cipher_encrypt(
943 &self,
944 algorithm: CipherAlgorithm,
945 slot_id: u8,
946 data: &mut Vec<u8>,
947 ) -> AtcaStatus {
948 if self.check_that_configuration_is_not_locked(true) {
949 return AtcaStatus::AtcaNotLocked;
950 }
951 if !self.is_aes_enabled() {
952 return AtcaStatus::AtcaBadParam;
954 }
955
956 match algorithm {
957 CipherAlgorithm::Ctr(cipher_param) => self.cipher_aes_ctr(cipher_param, slot_id, data),
958 CipherAlgorithm::Cfb(cipher_param) => {
959 self.cipher_aes_cfb(cipher_param, slot_id, data, CipherOperation::Encrypt)
960 }
961 CipherAlgorithm::Ofb(cipher_param) => {
962 self.cipher_aes_ofb(cipher_param, slot_id, data, CipherOperation::Encrypt)
963 }
964 CipherAlgorithm::Ecb(cipher_param) => {
965 self.cipher_aes_ecb(cipher_param, slot_id, data, CipherOperation::Encrypt)
966 }
967 CipherAlgorithm::Cbc(cipher_param) => {
968 self.cipher_aes_cbc(cipher_param, slot_id, data, CipherOperation::Encrypt)
969 }
970 CipherAlgorithm::CbcPkcs7(cipher_param) => {
971 self.cipher_aes_cbc_pkcs7(cipher_param, slot_id, data, CipherOperation::Encrypt)
972 }
973 _ => AtcaStatus::AtcaUnimplemented,
974 }
975 } fn cipher_decrypt(
979 &self,
980 algorithm: CipherAlgorithm,
981 slot_id: u8,
982 data: &mut Vec<u8>,
983 ) -> AtcaStatus {
984 if self.check_that_configuration_is_not_locked(true) {
985 return AtcaStatus::AtcaNotLocked;
986 }
987 if !self.is_aes_enabled() {
988 return AtcaStatus::AtcaBadParam;
990 }
991
992 match algorithm {
993 CipherAlgorithm::Ctr(cipher_param) => self.cipher_aes_ctr(cipher_param, slot_id, data),
994 CipherAlgorithm::Cfb(cipher_param) => {
995 self.cipher_aes_cfb(cipher_param, slot_id, data, CipherOperation::Decrypt)
996 }
997 CipherAlgorithm::Ofb(cipher_param) => {
998 self.cipher_aes_ofb(cipher_param, slot_id, data, CipherOperation::Decrypt)
999 }
1000 CipherAlgorithm::Ecb(cipher_param) => {
1001 self.cipher_aes_ecb(cipher_param, slot_id, data, CipherOperation::Decrypt)
1002 }
1003 CipherAlgorithm::Cbc(cipher_param) => {
1004 self.cipher_aes_cbc(cipher_param, slot_id, data, CipherOperation::Decrypt)
1005 }
1006 CipherAlgorithm::CbcPkcs7(cipher_param) => {
1007 self.cipher_aes_cbc_pkcs7(cipher_param, slot_id, data, CipherOperation::Decrypt)
1008 }
1009 _ => AtcaStatus::AtcaUnimplemented,
1010 }
1011 } fn aead_encrypt(
1015 &self,
1016 algorithm: AeadAlgorithm,
1017 slot_id: u8,
1018 data: &mut Vec<u8>,
1019 ) -> Result<Vec<u8>, AtcaStatus> {
1020 if self.check_that_configuration_is_not_locked(true) {
1021 return Err(AtcaStatus::AtcaNotLocked);
1022 }
1023 if !self.is_aes_enabled() {
1024 return Err(AtcaStatus::AtcaBadParam);
1026 }
1027
1028 match algorithm {
1029 AeadAlgorithm::Ccm(aead_param) => self.encrypt_aes_ccm(aead_param, slot_id, data),
1030 AeadAlgorithm::Gcm(aead_param) => self.encrypt_aes_gcm(aead_param, slot_id, data),
1031 }
1032 } fn aead_decrypt(
1036 &self,
1037 algorithm: AeadAlgorithm,
1038 slot_id: u8,
1039 data: &mut Vec<u8>,
1040 ) -> Result<bool, AtcaStatus> {
1041 if self.check_that_configuration_is_not_locked(true) {
1042 return Err(AtcaStatus::AtcaNotLocked);
1043 }
1044 if !self.is_aes_enabled() {
1045 return Err(AtcaStatus::AtcaBadParam);
1047 }
1048
1049 match algorithm {
1050 AeadAlgorithm::Ccm(aead_param) => self.decrypt_aes_ccm(aead_param, slot_id, data),
1051 AeadAlgorithm::Gcm(aead_param) => self.decrypt_aes_gcm(aead_param, slot_id, data),
1052 }
1053 } fn mac_compute(
1057 &self,
1058 algorithm: MacAlgorithm,
1059 slot_id: u8,
1060 data: &[u8],
1061 ) -> Result<Vec<u8>, AtcaStatus> {
1062 if self.check_that_configuration_is_not_locked(true) {
1063 return Err(AtcaStatus::AtcaNotLocked);
1064 }
1065 if (discriminant(&algorithm) != discriminant(&MacAlgorithm::HmacSha256(Default::default())))
1066 && !self.is_aes_enabled()
1067 {
1068 return Err(AtcaStatus::AtcaBadParam);
1070 }
1071
1072 match algorithm {
1073 MacAlgorithm::HmacSha256(mac_param) => {
1074 self.compute_mac_hmac_sha256(mac_param, slot_id, data)
1075 }
1076 MacAlgorithm::Cbcmac(mac_param) => self.compute_mac_cbcmac(mac_param, slot_id, data),
1077 MacAlgorithm::Cmac(mac_param) => self.compute_mac_cmac(mac_param, slot_id, data),
1078 }
1079 } fn mac_verify(
1083 &self,
1084 algorithm: MacAlgorithm,
1085 slot_id: u8,
1086 data: &[u8],
1087 ) -> Result<bool, AtcaStatus> {
1088 if self.check_that_configuration_is_not_locked(true) {
1089 return Err(AtcaStatus::AtcaNotLocked);
1090 }
1091 if (discriminant(&algorithm) != discriminant(&MacAlgorithm::HmacSha256(Default::default())))
1092 && !self.is_aes_enabled()
1093 {
1094 return Err(AtcaStatus::AtcaBadParam);
1096 }
1097
1098 match algorithm {
1099 MacAlgorithm::HmacSha256(mac_param) => {
1100 self.verify_mac_hmac_sha256(mac_param, slot_id, data)
1101 }
1102 MacAlgorithm::Cbcmac(mac_param) => self.verify_mac_cbcmac(mac_param, slot_id, data),
1103 MacAlgorithm::Cmac(mac_param) => self.verify_mac_cmac(mac_param, slot_id, data),
1104 }
1105 } fn get_device_type(&self) -> AtcaDeviceType {
1109 AtcaDeviceType::from(unsafe {
1110 let _guard = self
1111 .api_mutex
1112 .lock()
1113 .expect("Could not lock atcab API mutex");
1114 cryptoauthlib_sys::atcab_get_device_type()
1115 })
1116 } fn get_config(&self, atca_slots: &mut Vec<AtcaSlot>) -> AtcaStatus {
1121 atca_slots.clear();
1122 for idx in 0..self.slots.len() {
1123 atca_slots.push(self.slots[idx])
1124 }
1125 AtcaStatus::AtcaSuccess
1126 } fn info_cmd(&self, command: InfoCmdType) -> Result<Vec<u8>, AtcaStatus> {
1130 let mut out_data: Vec<u8> = vec![0; 4];
1131 let param2 = 0;
1132 match command {
1133 InfoCmdType::Revision => (),
1134 InfoCmdType::State => (),
1135 _ => return Err(AtcaStatus::AtcaUnimplemented),
1136 }
1137 let result = AtcaStatus::from(unsafe {
1138 let _guard = self
1139 .api_mutex
1140 .lock()
1141 .expect("Could not lock atcab API mutex");
1142 cryptoauthlib_sys::atcab_info_base(command as u8, param2, out_data.as_mut_ptr())
1143 });
1144 match result {
1145 AtcaStatus::AtcaSuccess => Ok(out_data),
1146 _ => Err(result),
1147 }
1148 } fn add_access_key(&self, slot_id: u8, access_key: &[u8]) -> AtcaStatus {
1154 if let Err(err) = self.access_key_setup_parameters_check(slot_id) {
1155 return err;
1156 };
1157
1158 if access_key.len() != ATCA_KEY_SIZE {
1159 return AtcaStatus::AtcaInvalidSize;
1160 }
1161
1162 let access_keys_mutex = self
1163 .access_keys
1164 .lock()
1165 .expect("Could not lock 'access_keys' mutex");
1166
1167 let access_keys_obj = access_keys_mutex.try_borrow_mut();
1168
1169 match access_keys_obj {
1170 Err(_) => AtcaStatus::AtcaFuncFail,
1171 Ok(mut access_keys) => {
1172 let mut key_arr: [u8; ATCA_KEY_SIZE] = [0; ATCA_KEY_SIZE];
1173 key_arr.copy_from_slice(&access_key[0..]);
1174 access_keys.insert(slot_id, key_arr);
1175 AtcaStatus::AtcaSuccess
1176 }
1177 }
1178 } fn flush_access_keys(&self) -> AtcaStatus {
1183 let access_keys_mutex = self
1184 .access_keys
1185 .lock()
1186 .expect("Could not lock 'access_keys' mutex");
1187
1188 let access_keys_obj = access_keys_mutex.try_borrow_mut();
1189
1190 match access_keys_obj {
1191 Err(_) => AtcaStatus::AtcaFuncFail,
1192 Ok(mut access_keys) => {
1193 access_keys.clear();
1194 access_keys.shrink_to_fit();
1195 AtcaStatus::AtcaSuccess
1196 }
1197 }
1198 } fn wakeup(&self) -> AtcaStatus {
1202 AtcaStatus::from(unsafe {
1203 let _guard = self
1204 .api_mutex
1205 .lock()
1206 .expect("Could not lock atcab API mutex");
1207 cryptoauthlib_sys::atcab_wakeup()
1208 })
1209 } fn sleep(&self) -> AtcaStatus {
1213 AtcaStatus::from(unsafe {
1214 let _guard = self
1215 .api_mutex
1216 .lock()
1217 .expect("Could not lock atcab API mutex");
1218 cryptoauthlib_sys::atcab_sleep()
1219 })
1220 } fn release(&self) -> AtcaStatus {
1228 if !ATECC_RESOURCE_MANAGER.lock().unwrap().release() {
1229 return AtcaStatus::AtcaBadParam;
1230 }
1231 AtcaStatus::from(unsafe {
1232 let _guard = self
1233 .api_mutex
1234 .lock()
1235 .expect("Could not lock atcab API mutex");
1236 Box::from_raw(self.iface_cfg_ptr.ptr);
1239 cryptoauthlib_sys::atcab_release()
1240 })
1241 } fn read_zone(&self, zone: u8, slot: u16, block: u8, offset: u8, data: &mut [u8]) -> AtcaStatus {
1251 AtcaStatus::from(unsafe {
1252 let _guard = self
1253 .api_mutex
1254 .lock()
1255 .expect("Could not lock atcab API mutex");
1256 cryptoauthlib_sys::atcab_read_zone(
1257 zone,
1258 slot,
1259 block,
1260 offset,
1261 data.as_mut_ptr(),
1262 data.len() as u8,
1263 )
1264 })
1265 } fn read_config_zone(&self, config_data: &mut Vec<u8>) -> AtcaStatus {
1271 config_data.resize(self.get_config_buffer_size(), 0);
1272
1273 AtcaStatus::from(unsafe {
1274 let _guard = self
1275 .api_mutex
1276 .lock()
1277 .expect("Could not lock atcab API mutex");
1278 cryptoauthlib_sys::atcab_read_config_zone(config_data.as_mut_ptr())
1279 })
1280 } #[allow(dead_code)]
1285 fn cmp_config_zone(&self, config_data: &mut [u8]) -> Result<bool, AtcaStatus> {
1286 let buffer_size = self.get_config_buffer_size();
1287 if config_data.len() != buffer_size {
1288 return Err(AtcaStatus::AtcaBadParam);
1289 }
1290 let mut same_config: bool = false;
1291 let result = AtcaStatus::from(unsafe {
1292 let _guard = self
1293 .api_mutex
1294 .lock()
1295 .expect("Could not lock atcab API mutex");
1296 cryptoauthlib_sys::atcab_cmp_config_zone(config_data.as_mut_ptr(), &mut same_config)
1297 });
1298 if AtcaStatus::AtcaSuccess == result {
1299 Ok(same_config)
1300 } else {
1301 Err(result)
1302 }
1303 } fn get_access_key(&self, slot_id: u8, key: &mut Vec<u8>) -> AtcaStatus {
1309 if let Err(err) = self.access_key_setup_parameters_check(slot_id) {
1310 return err;
1311 };
1312
1313 key.resize(ATCA_KEY_SIZE, 0);
1314
1315 let access_keys_mutex = self
1316 .access_keys
1317 .lock()
1318 .expect("Could not lock 'access_keys' mutex");
1319
1320 let access_keys_obj = access_keys_mutex.try_borrow_mut();
1321
1322 match access_keys_obj {
1323 Err(_) => AtcaStatus::AtcaFuncFail,
1324 Ok(access_keys) => match access_keys.get(&slot_id) {
1325 None => AtcaStatus::AtcaInvalidId,
1326 Some(access_key) => {
1327 *key = access_key.to_vec();
1328 AtcaStatus::AtcaSuccess
1329 }
1330 },
1331 }
1332 } fn get_slot_capacity(&self, slot_id: u8) -> AtcaSlotCapacity {
1337 let mut slot_capacity: AtcaSlotCapacity = Default::default();
1338 match slot_id {
1339 0x00..=0x07 => {
1340 slot_capacity.blocks = 2;
1341 slot_capacity.last_block_bytes = 4;
1342 slot_capacity.bytes = 36;
1343 }
1344 0x08 => {
1345 slot_capacity.blocks = 13;
1346 slot_capacity.last_block_bytes = 32;
1347 slot_capacity.bytes = 416;
1348 }
1349 0x09..=0x0F => {
1350 slot_capacity.blocks = 3;
1351 slot_capacity.last_block_bytes = 8;
1352 slot_capacity.bytes = 72;
1353 }
1354 _ => {}
1355 }
1356 slot_capacity
1357 } fn write_p256_ecc_key_to_slot(&self, key_data: &[u8], slot: u16) -> AtcaStatus {
1365 match key_data.len() {
1366 ATCA_ATECC_PUB_KEY_SIZE => {
1367 if slot < ATCA_ATECC_MIN_SLOT_IDX_FOR_PUB_KEY as u16 {
1368 return AtcaStatus::AtcaInvalidId;
1369 }
1370
1371 AtcaStatus::from(unsafe {
1372 let _guard = self
1373 .api_mutex
1374 .lock()
1375 .expect("Could not lock atcab API mutex");
1376 cryptoauthlib_sys::atcab_write_pubkey(slot, key_data.as_ptr())
1377 })
1378 }
1379 ATCA_ATECC_PRIV_KEY_SIZE => {
1380 let mut temp_key: Vec<u8> = vec![0; 4];
1381 temp_key.extend_from_slice(key_data);
1382
1383 if let Some(write_key_idx) = self.get_write_key_idx(slot as u8) {
1384 let mut write_key = vec![0; ATCA_KEY_SIZE];
1385 let result = self.get_access_key(write_key_idx, &mut write_key);
1386
1387 if AtcaStatus::AtcaSuccess == result {
1388 let mut num_in: [u8; ATCA_NONCE_NUMIN_SIZE] = [0; ATCA_NONCE_NUMIN_SIZE];
1389
1390 AtcaStatus::from(unsafe {
1391 let _guard = self
1392 .api_mutex
1393 .lock()
1394 .expect("Could not lock atcab API mutex");
1395 cryptoauthlib_sys::atcab_priv_write(
1396 slot,
1397 temp_key.as_ptr(),
1398 write_key_idx as u16,
1399 write_key.as_ptr(),
1400 num_in.as_mut_ptr(),
1401 )
1402 })
1403 } else {
1404 result
1405 }
1406 } else {
1407 AtcaStatus::AtcaBadParam
1408 }
1409 }
1410 _ => AtcaStatus::AtcaInvalidSize,
1411 }
1412 } fn write_aes_key_to_slot(&self, key_data: &[u8], slot: u16) -> AtcaStatus {
1416 const BLOCK_IDX: u8 = 0;
1417
1418 if key_data.len() != ATCA_AES_KEY_SIZE {
1419 return AtcaStatus::AtcaInvalidSize;
1420 }
1421
1422 let mut temp_key: Vec<u8> = vec![0x00; ATCA_BLOCK_SIZE];
1423 temp_key[..key_data.len()].copy_from_slice(key_data);
1424
1425 if slot != ATCA_ATECC_TEMPKEY_KEYID {
1426 self.write_slot(slot, BLOCK_IDX, &temp_key)
1427 } else {
1428 self.nonce(NonceTarget::TempKey, &temp_key)
1429 }
1430 } fn write_sha_or_text_key_to_slot(&self, key_data: &[u8], slot: u16) -> AtcaStatus {
1434 if (ATCA_ATECC_TEMPKEY_KEYID == slot) && (key_data.len() <= ATCA_BLOCK_SIZE) {
1435 let mut temp_key: Vec<u8> = vec![0x00; ATCA_NONCE_SIZE];
1436 temp_key[..key_data.len()].copy_from_slice(key_data);
1437 return self.nonce(NonceTarget::TempKey, &temp_key);
1438 }
1439 if key_data.len() > self.get_slot_capacity(slot as u8).bytes as usize {
1440 return AtcaStatus::AtcaInvalidSize;
1441 }
1442
1443 let mut start_pos: usize = 0;
1444 let mut block: u8 = 0;
1445 let mut shift: usize = min(key_data.len(), ATCA_BLOCK_SIZE);
1446 let mut result: AtcaStatus = AtcaStatus::AtcaUnknown;
1447
1448 while shift > 0 {
1449 match shift {
1450 ATCA_BLOCK_SIZE => {
1451 result = self.write_slot(slot, block, &key_data[start_pos..(start_pos + shift)])
1452 }
1453 _ => {
1454 let mut buffer: [u8; ATCA_BLOCK_SIZE] = [0x00; ATCA_BLOCK_SIZE];
1455 buffer[..shift].clone_from_slice(&key_data[start_pos..(start_pos + shift)]);
1456 result = self.write_slot(slot, block, &buffer)
1457 }
1458 }
1459 if result != AtcaStatus::AtcaSuccess {
1460 return result;
1461 }
1462
1463 start_pos += shift;
1464 block += 1;
1465 let remaining_bytes = key_data.len() - start_pos;
1466 if remaining_bytes < ATCA_BLOCK_SIZE {
1467 shift = remaining_bytes
1468 }
1469 }
1470
1471 result
1472 } fn read_aes_key_from_slot(&self, slot_id: u8, key: &mut Vec<u8>) -> AtcaStatus {
1476 const BLOCK_IDX: u8 = 0;
1477
1478 if slot_id >= ATCA_ATECC_SLOTS_COUNT {
1479 return AtcaStatus::AtcaInvalidId;
1480 };
1481
1482 let slot_data = self.slots[slot_id as usize].config;
1483 if KeyType::Aes != slot_data.key_type {
1484 return AtcaStatus::AtcaBadParam;
1485 }
1486
1487 let mut data_block: [u8; ATCA_BLOCK_SIZE] = [0; ATCA_BLOCK_SIZE];
1488
1489 let result = self.read_slot(slot_id as u16, BLOCK_IDX, &mut data_block);
1490
1491 if AtcaStatus::AtcaSuccess == result {
1492 *key = data_block[..ATCA_AES_KEY_SIZE].to_vec()
1493 }
1494
1495 result
1496 } fn read_sha_or_text_key_from_slot(&self, slot_id: u8, data: &mut [u8]) -> AtcaStatus {
1500 if slot_id >= ATCA_ATECC_SLOTS_COUNT {
1501 return AtcaStatus::AtcaInvalidId;
1502 };
1503
1504 let slot_data = self.slots[slot_id as usize].config;
1505 if KeyType::ShaOrText != slot_data.key_type {
1506 return AtcaStatus::AtcaBadParam;
1507 }
1508 if data.len() > self.get_slot_capacity(slot_id).bytes as usize {
1509 return AtcaStatus::AtcaInvalidSize;
1510 }
1511
1512 let mut data_block: [u8; ATCA_BLOCK_SIZE] = [0x00; ATCA_BLOCK_SIZE];
1513 let mut result: AtcaStatus = AtcaStatus::AtcaUnknown;
1514
1515 let modulo = data.len() % ATCA_BLOCK_SIZE;
1516 let runs = (data.len() / ATCA_BLOCK_SIZE) + (0 != modulo) as usize - 1;
1517
1518 for idx in 0..=runs {
1519 result = self.read_slot(slot_id as u16, idx as u8, &mut data_block);
1520 if AtcaStatus::AtcaSuccess != result {
1521 break;
1522 }
1523
1524 let start_pos: usize = idx * ATCA_BLOCK_SIZE;
1525 let shift: usize = match (runs == idx) && (0 != modulo) {
1526 false => ATCA_BLOCK_SIZE,
1527 _ => modulo,
1528 };
1529 data[start_pos..(start_pos + shift)].copy_from_slice(&data_block[..shift])
1530 }
1531
1532 result
1533 } fn encryption_key_setup_parameters_check(
1538 &self,
1539 key_type: KeyType,
1540 slot_id: u8,
1541 ) -> Result<(), AtcaStatus> {
1542 if slot_id > ATCA_ATECC_SLOTS_COUNT {
1543 return Err(AtcaStatus::AtcaInvalidId);
1544 }
1545 if ((key_type == KeyType::Aes) && !self.chip_options.aes_enabled)
1546 || ((slot_id < ATCA_ATECC_SLOTS_COUNT)
1547 && (key_type != self.slots[slot_id as usize].config.key_type))
1548 {
1549 return Err(AtcaStatus::AtcaBadParam);
1550 }
1551 Ok(())
1552 } fn access_key_setup_parameters_check(&self, slot_id: u8) -> Result<(), AtcaStatus> {
1557 if (slot_id > ATCA_ATECC_SLOTS_COUNT) ||
1558 ((slot_id == ATCA_ATECC_SLOTS_COUNT) &&
1560 (self.get_device_type() != AtcaDeviceType::ATECC608A))
1561 {
1562 return Err(AtcaStatus::AtcaInvalidId);
1563 }
1564 Ok(())
1565 } fn get_write_key_idx(&self, slot_id: u8) -> Option<u8> {
1571 if slot_id < ATCA_ATECC_SLOTS_COUNT {
1572 let slot_data = self.slots[slot_id as usize].config;
1573 if slot_data.write_config == WriteConfig::Encrypt {
1574 Some(slot_data.write_key)
1575 } else {
1576 None
1577 }
1578 } else {
1579 None
1580 }
1581 } fn get_read_key_idx(&self, slot_id: u8) -> Option<u8> {
1587 if slot_id < ATCA_ATECC_SLOTS_COUNT {
1588 let slot_data = self.slots[slot_id as usize].config;
1589 if slot_data.read_key.encrypt_read
1590 && slot_data.is_secret
1591 && !slot_data.ecc_key_attr.is_private
1592 {
1593 Some(slot_data.read_key.slot_number)
1594 } else {
1595 None
1596 }
1597 } else {
1598 None
1599 }
1600 } #[inline]
1604 fn check_that_configuration_is_not_locked(&self, both: bool) -> bool {
1605 (!self.data_zone_locked && both) || !self.config_zone_locked
1606 } fn is_locked(&self, config_data: &[u8], zone: u8) -> bool {
1610 const LOCK_DATA_BYTE_INDEX: usize = 86;
1611 const LOCK_CONFIG_BYTE_INDEX: usize = LOCK_DATA_BYTE_INDEX + 1;
1612
1613 match zone {
1614 ATCA_LOCK_ZONE_CONFIG => config_data[LOCK_CONFIG_BYTE_INDEX] != 0x55,
1615 ATCA_LOCK_ZONE_DATA => config_data[LOCK_DATA_BYTE_INDEX] != 0x55,
1616 _ => false,
1617 }
1618 } fn get_chip_options_data_from_chip_config_data(&mut self, config_data: &[u8]) {
1621 const INDEX_OF_AES_BYTE: usize = 13;
1622 const KDF_IV_LOC_BYTE: usize = 72;
1623 const KDF_IV_STR_FIRST_BYTE: usize = KDF_IV_LOC_BYTE + 1;
1624 const KDF_IV_STR_SECOND_BYTE: usize = KDF_IV_STR_FIRST_BYTE + 1;
1625 const CHIP_OPTIONS_FIRST_BYTE: usize = 90;
1626 const CHIP_OPTIONS_SECOND_BYTE: usize = CHIP_OPTIONS_FIRST_BYTE + 1;
1627 const IO_KEY_EN_POS: u8 = 1;
1628 const KDF_AES_EN_POS: u8 = 2;
1629
1630 self.chip_options = ChipOptions {
1631 io_key_enabled: atcab_get_bit_value(
1632 config_data[CHIP_OPTIONS_FIRST_BYTE],
1633 IO_KEY_EN_POS,
1634 ),
1635 io_key_in_slot: (config_data[CHIP_OPTIONS_SECOND_BYTE] >> 4) & 0b00001111,
1636 kdf_aes_enabled: atcab_get_bit_value(
1637 config_data[CHIP_OPTIONS_FIRST_BYTE],
1638 KDF_AES_EN_POS,
1639 ),
1640 ecdh_output_protection: (config_data[CHIP_OPTIONS_SECOND_BYTE] & 0b00000011).into(),
1641 kdf_output_protection: ((config_data[CHIP_OPTIONS_SECOND_BYTE] >> 2) & 0b00000011)
1642 .into(),
1643 aes_enabled: (config_data[INDEX_OF_AES_BYTE] & 0x01) != 0x00,
1644 kdf_iv_enabled: config_data[KDF_IV_LOC_BYTE] != 0xF0,
1645 kdf_iv_location_at: config_data[KDF_IV_LOC_BYTE] as usize,
1646 kdf_iv_str: [
1647 config_data[KDF_IV_STR_FIRST_BYTE],
1648 config_data[KDF_IV_STR_SECOND_BYTE],
1649 ],
1650 }
1651 } fn get_config_from_chip(&self, config_data: &mut Vec<u8>) -> AtcaStatus {
1655 let result = self.read_config_zone(config_data);
1656 if AtcaStatus::AtcaSuccess != result {
1657 return result;
1658 }
1659 if config_data.len() != self.get_config_buffer_size() {
1660 return AtcaStatus::AtcaBadParam;
1661 }
1662 AtcaStatus::AtcaSuccess
1663 } fn get_config_buffer_size(&self) -> usize {
1667 let device_type = self.get_device_type();
1668 match device_type {
1669 AtcaDeviceType::ATECC508A | AtcaDeviceType::ATECC608A | AtcaDeviceType::ATECC108A => {
1670 ATCA_ATECC_CONFIG_BUFFER_SIZE
1671 }
1672 _ => ATCA_ATSHA_CONFIG_BUFFER_SIZE,
1673 }
1674 } fn get_serial_number(&self, config_data: &[u8]) -> [u8; ATCA_SERIAL_NUM_SIZE] {
1678 let mut serial_number: [u8; ATCA_SERIAL_NUM_SIZE] = [0; ATCA_SERIAL_NUM_SIZE];
1679
1680 serial_number[..4].clone_from_slice(&config_data[..4]);
1681 serial_number[4..].clone_from_slice(&config_data[8..=12]);
1682
1683 serial_number
1684 } fn read_slot(&self, slot: u16, block: u8, data: &mut [u8]) -> AtcaStatus {
1688 let slot_data = self.slots[slot as usize].config;
1689 let result: AtcaStatus;
1690
1691 if slot_data.is_secret && slot_data.read_key.encrypt_read {
1692 let num_in: [u8; ATCA_NONCE_NUMIN_SIZE] = [0; ATCA_NONCE_NUMIN_SIZE];
1693 result = self.read_slot_with_encryption(slot as u16, block, data, &num_in)
1694 } else {
1695 const OFFSET: u8 = 0;
1696 result = self.read_zone(ATCA_ZONE_DATA, slot as u16, block, OFFSET, data)
1697 }
1698
1699 result
1700 } fn read_slot_with_encryption(
1704 &self,
1705 slot: u16,
1706 block: u8,
1707 data: &mut [u8],
1708 num_in: &[u8],
1709 ) -> AtcaStatus {
1710 if (data.len() != ATCA_BLOCK_SIZE) || (num_in.len() != ATCA_NONCE_NUMIN_SIZE) {
1711 return AtcaStatus::AtcaInvalidSize;
1712 }
1713 if (slot >= ATCA_ATECC_SLOTS_COUNT as u16)
1714 || (block >= self.get_slot_capacity(slot as u8).blocks)
1715 {
1716 return AtcaStatus::AtcaInvalidId;
1717 }
1718
1719 if let Some(read_key_idx) = self.get_read_key_idx(slot as u8) {
1720 let mut read_key = vec![0; ATCA_KEY_SIZE];
1721 let result = self.get_access_key(read_key_idx, &mut read_key);
1722
1723 if AtcaStatus::AtcaSuccess == result {
1724 AtcaStatus::from(unsafe {
1725 let _guard = self
1726 .api_mutex
1727 .lock()
1728 .expect("Could not lock atcab API mutex");
1729 cryptoauthlib_sys::atcab_read_enc(
1730 slot,
1731 block,
1732 data.as_mut_ptr(),
1733 read_key.as_ptr(),
1734 read_key_idx as u16,
1735 num_in.as_ptr(),
1736 )
1737 })
1738 } else {
1739 result
1740 }
1741 } else {
1742 AtcaStatus::AtcaBadParam
1743 }
1744 } fn write_slot(&self, slot: u16, block: u8, data: &[u8]) -> AtcaStatus {
1748 const OFFSET: u8 = 0;
1749
1750 match self.slots[slot as usize].config.write_config {
1751 WriteConfig::Always => self.write_zone(ATCA_ZONE_DATA, slot, block, OFFSET, data),
1752 WriteConfig::Encrypt => {
1753 let num_in: [u8; ATCA_NONCE_NUMIN_SIZE] = [0; ATCA_NONCE_NUMIN_SIZE];
1754 self.write_slot_with_encryption(slot, block, data, &num_in)
1755 }
1756 _ => AtcaStatus::AtcaBadParam,
1757 }
1758 } fn write_zone(&self, zone: u8, slot: u16, block: u8, offset: u8, data: &[u8]) -> AtcaStatus {
1762 AtcaStatus::from(unsafe {
1763 let _guard = self
1764 .api_mutex
1765 .lock()
1766 .expect("Could not lock atcab API mutex");
1767 cryptoauthlib_sys::atcab_write_zone(
1768 zone,
1769 slot,
1770 block,
1771 offset,
1772 data.as_ptr(),
1773 data.len() as u8,
1774 )
1775 })
1776 } fn write_slot_with_encryption(
1780 &self,
1781 slot: u16,
1782 block: u8,
1783 data: &[u8],
1784 num_in: &[u8],
1785 ) -> AtcaStatus {
1786 if (data.len() != ATCA_BLOCK_SIZE) || (num_in.len() != ATCA_NONCE_NUMIN_SIZE) {
1787 return AtcaStatus::AtcaInvalidSize;
1788 }
1789 if (slot >= ATCA_ATECC_SLOTS_COUNT as u16)
1790 || (block >= self.get_slot_capacity(slot as u8).blocks)
1791 {
1792 return AtcaStatus::AtcaInvalidId;
1793 }
1794
1795 if let Some(write_key_idx) = self.get_write_key_idx(slot as u8) {
1796 let mut write_key = vec![0; ATCA_KEY_SIZE];
1797 let result = self.get_access_key(write_key_idx, &mut write_key);
1798
1799 if AtcaStatus::AtcaSuccess == result {
1800 AtcaStatus::from(unsafe {
1801 let _guard = self
1802 .api_mutex
1803 .lock()
1804 .expect("Could not lock atcab API mutex");
1805 cryptoauthlib_sys::atcab_write_enc(
1806 slot,
1807 block,
1808 data.as_ptr(),
1809 write_key.as_ptr(),
1810 write_key_idx as u16,
1811 num_in.as_ptr(),
1812 )
1813 })
1814 } else {
1815 result
1816 }
1817 } else {
1818 AtcaStatus::AtcaBadParam
1819 }
1820 } }
1822
1823fn atcab_get_bit_value(byte: u8, bit_pos: u8) -> bool {
1828 if bit_pos < 8 {
1829 ((byte >> bit_pos) & 1) != 0
1830 } else {
1831 false
1832 }
1833}
1834
1835fn atcab_get_write_config(data: u8) -> WriteConfig {
1836 match data & 0b00001111 {
1837 0 => WriteConfig::Always,
1838 1 => WriteConfig::PubInvalid,
1839 2..=3 => WriteConfig::Never,
1840 4..=7 => WriteConfig::Encrypt,
1841 8..=11 => WriteConfig::Never,
1842 _ => WriteConfig::Encrypt,
1843 }
1844}
1845
1846fn atcab_get_key_type(data: u8) -> KeyType {
1847 match data & 0b00000111 {
1848 4 => KeyType::P256EccKey,
1849 6 => KeyType::Aes,
1850 7 => KeyType::ShaOrText,
1851 _ => KeyType::Rfu,
1852 }
1853}
1854
1855pub fn atcab_get_slots_config_from_config_data(config_data: &[u8], atca_slots: &mut Vec<AtcaSlot>) {
1856 const IDX_SLOT_LOCKED: usize = 88;
1857 const IDX_SLOT_CONFIG: usize = 20;
1858 const IDX_KEY_CONFIG: usize = 96;
1859 for idx in 0..ATCA_ATECC_SLOTS_COUNT {
1860 let slot_cfg_pos = IDX_SLOT_CONFIG + (idx * 2) as usize;
1861 let key_cfg_pos = IDX_KEY_CONFIG + (idx * 2) as usize;
1862 let read_key_struct = ReadKey {
1863 encrypt_read: atcab_get_bit_value(config_data[slot_cfg_pos], 6),
1864 slot_number: config_data[slot_cfg_pos] & 0b00001111,
1865 };
1866 let ecc_key_attr_struct = EccKeyAttr {
1867 is_private: atcab_get_bit_value(config_data[key_cfg_pos], 0),
1868 ext_sign: atcab_get_bit_value(config_data[slot_cfg_pos], 0),
1869 int_sign: atcab_get_bit_value(config_data[slot_cfg_pos], 1),
1870 ecdh_operation: atcab_get_bit_value(config_data[slot_cfg_pos], 2),
1871 ecdh_secret_out: atcab_get_bit_value(config_data[slot_cfg_pos], 3),
1872 };
1873 let config_struct = SlotConfig {
1874 write_config: atcab_get_write_config(config_data[slot_cfg_pos + 1] >> 4),
1875 key_type: atcab_get_key_type(config_data[key_cfg_pos] >> 2),
1876 read_key: read_key_struct,
1877 ecc_key_attr: ecc_key_attr_struct,
1878 x509id: (config_data[key_cfg_pos + 1] >> 6) & 0b00000011,
1879 auth_key: config_data[key_cfg_pos + 1] & 0b00001111,
1880 write_key: config_data[slot_cfg_pos + 1] & 0b00001111,
1881 is_secret: atcab_get_bit_value(config_data[slot_cfg_pos], 7),
1882 limited_use: atcab_get_bit_value(config_data[slot_cfg_pos], 5),
1883 no_mac: atcab_get_bit_value(config_data[slot_cfg_pos], 4),
1884 persistent_disable: atcab_get_bit_value(config_data[key_cfg_pos + 1], 4),
1885 req_auth: atcab_get_bit_value(config_data[key_cfg_pos], 7),
1886 req_random: atcab_get_bit_value(config_data[key_cfg_pos], 6),
1887 lockable: atcab_get_bit_value(config_data[key_cfg_pos], 5),
1888 pub_info: atcab_get_bit_value(config_data[key_cfg_pos], 1),
1889 };
1890 let slot = AtcaSlot {
1891 id: idx,
1892 is_locked: {
1893 let index = IDX_SLOT_LOCKED + (idx / 8) as usize;
1894 let bit_position = idx % 8;
1895 let bit_value = (config_data[index] >> bit_position) & 1;
1896 bit_value != 1
1897 },
1898 config: config_struct,
1899 };
1900 atca_slots.push(slot);
1901 }
1902}