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}