rust_cryptoauthlib/hw_impl/
provisioning.rs

1// ATTENTION these functions should be called knowing what you are doing !!!
2//
3// The lack of tests for this module is intentional because, in most cases,
4// these functions can only be called once and block the possibility of further changes to the chip.
5// --------------------------------------------------------------------------------------------------
6//
7// Below is the content of the test configuration for the ATECC608A chip, used in testing this crate.
8// This configuration was created for testing purposes only,
9// DO NOT USE it in target solutions, for security reasons!!!
10//
11// const TEST_CONFIG_DATA: &[u8] = &[
12//     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
13//     0xC0, 0x00, 0x00, 0x01, 0x8F, 0x20, 0xC6, 0xE6, 0x86, 0x66, 0x85, 0x66, 0xC6, 0x66, 0xC6, 0x46,
14//     0x8F, 0x0F, 0x9F, 0x8F, 0x00, 0x0F, 0xC6, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0B, 0x1F,
15//     0xC6, 0x76, 0xC6, 0xF6, 0x3F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
16//     0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x03, 0xB7, 0x00, 0x69, 0x76, 0x00, 0x00, 0x00, 0x00, 0x00,
17//     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x55, 0x55, 0xFF, 0xFF, 0x0E, 0x60, 0x00, 0x00, 0x00, 0x00,
18//     0x33, 0x00, 0x1C, 0x00, 0x73, 0x00, 0x13, 0x00, 0x18, 0x00, 0x38, 0x00, 0x7C, 0x00, 0x1C, 0x00,
19//     0x3C, 0x00, 0x1A, 0x00, 0x3C, 0x00, 0x30, 0x00, 0x3C, 0x00, 0x12, 0x00, 0x18, 0x00, 0x1A, 0x00,
20// ];
21// --------------------------------------------------------------------------------------------------
22//
23// In addition, for all tests to run correctly, to slot 6 you must upload encryption key,
24// the content of which is in constant 'WRITE_KEY' in file 'hw_backend_common.rs'
25//
26// --------------------------------------------------------------------------------------------------
27
28use super::{AtcaStatus, AteccDevice};
29
30use super::ATCA_ATECC_SLOTS_COUNT;
31
32impl AteccDevice {
33    /// Execute this command prevents future modifications of the Configuration zone.
34    /// This command fails if the designated area is already locked.
35    pub(crate) fn lock_config_zone(&self) -> AtcaStatus {
36        AtcaStatus::from(unsafe {
37            let _guard = self
38                .api_mutex
39                .lock()
40                .expect("Could not lock atcab API mutex");
41            cryptoauthlib_sys::atcab_lock_config_zone()
42        })
43    } // AteccDevice::lock_config_zone()
44
45    /// Execute this command prevents future modifications of the Data and OTP zones.
46    /// This command fails if the designated area is already locked.
47    pub(crate) fn lock_data_zone(&self) -> AtcaStatus {
48        if !self.config_zone_locked {
49            return AtcaStatus::AtcaNotLocked;
50        }
51
52        AtcaStatus::from(unsafe {
53            let _guard = self
54                .api_mutex
55                .lock()
56                .expect("Could not lock atcab API mutex");
57            cryptoauthlib_sys::atcab_lock_data_zone()
58        })
59    } // AteccDevice::lock_data_zone()
60
61    /// Lock an individual slot in the data zone on an ATECC device. Not available for ATSHA devices.
62    /// Slot must be configured to be slot lockable slots[slot_idx].config.lockable = true.
63    /// This command fails if the designated area is already locked.
64    pub(crate) fn lock_slot(&self, slot_id: u8) -> AtcaStatus {
65        if !(self.config_zone_locked && self.data_zone_locked) {
66            return AtcaStatus::AtcaNotLocked;
67        }
68        if slot_id >= ATCA_ATECC_SLOTS_COUNT {
69            return AtcaStatus::AtcaInvalidId;
70        }
71        if !self.slots[slot_id as usize].config.lockable {
72            return AtcaStatus::AtcaBadParam;
73        }
74
75        AtcaStatus::from(unsafe {
76            let _guard = self
77                .api_mutex
78                .lock()
79                .expect("Could not lock atcab API mutex");
80            cryptoauthlib_sys::atcab_lock_data_slot(slot_id as u16)
81        })
82    } // AteccDevice::lock_slot()
83
84    /// Function for uploading configuration to the chip.
85    /// First 16 bytes of data are skipped as they are not writable. LockValue and LockConfig
86    /// are also skipped and can only be changed via the Lock command.
87    /// This command may fail if UserExtra and/or Selector bytes have already been set to non-zero values.
88    pub(crate) fn load_config_into_chip(&self, config: &[u8]) -> AtcaStatus {
89        if self.config_zone_locked {
90            return AtcaStatus::AtcaConfigZoneLocked;
91        }
92        if config.len() != self.get_config_buffer_size() {
93            return AtcaStatus::AtcaInvalidSize;
94        }
95
96        AtcaStatus::from(unsafe {
97            let _guard = self
98                .api_mutex
99                .lock()
100                .expect("Could not lock atcab API mutex");
101            cryptoauthlib_sys::atcab_write_config_zone(config.as_ptr())
102        })
103    } // AteccDevice::load_config_into_chip()
104}