Crates.io | Rusty_CryptoAuthLib |
lib.rs | Rusty_CryptoAuthLib |
version | 1.0.0 |
source | src |
created_at | 2020-08-27 07:40:49.98497 |
updated_at | 2020-09-19 08:52:02.14205 |
description | A platform agnostic I2C driver for Microchip's Crypto Authentication HW (i.e. secure element `ATECC608A`), written in pure Rust. |
homepage | https://github.com/nihalpasham/Rusty_CryptoAuthLib.git |
repository | https://github.com/nihalpasham/Rusty_CryptoAuthLib.git |
max_upload_size | |
id | 281312 |
size | 3,722,100 |
A platform agnostic I2C driver for Microchip's crypto-authentication device i.e. ATECC608a, written entirely in Rust. This library implements APIs required to communicate with Microchip Security device - ATECC608a.
The ATECC608A device is a member of the Microchip CryptoAuthenticationâ„¢ family of crypto engine authentication devices with highly secure hardware-based key storage.
The ATECC608A device has a flexible command set that allows use in many applications, including the following:
The device includes an EEPROM array which can be used for storage of up to 16 keys, certificates, miscellaneous read/write, read-only or secret data, consumption logging, and security configurations. Access to the various sections of memory can be restricted in a variety of ways and then the configuration can be locked to prevent changes. Access to the device is made through a standard I2C Interface at speeds of up to 1 Mb/s(see Section I2C Interface). The interface is compatible with standard Serial EEPROM I2C interface specifications.
The ATECC608A is a command-based device which receives commands from the system, executes those commands, and then returns a result or error code.
heapless
and Postcard
for command packet construction.
#![no_main]
#![no_std]
// #![allow(warnings)]
extern crate nrf52840_hal as hal;
extern crate panic_halt;
extern crate nrf52840_mdk;
use cortex_m_rt::{entry, exception};
use hal::gpio::{p0, p1};
use hal::target::Peripherals;
use hal::timer::Timer;
use hal::twim::{self, Twim};
// use cortex_m_semihosting::hprintln;
use Rusty_CryptoAuthLib::ATECC608A;
use nrf52840_mdk::Pins;
#[entry]
fn main() -> ! {
let p = Peripherals::take().unwrap();
let pins = Pins::new(p0::Parts::new(p.P0), p1::Parts::new(p.P1));
let scl = pins.p27.into_floating_input().degrade();
let sda = pins.p26.into_floating_input().degrade();
let i2c_pins = twim::Pins { scl, sda };
let i2c = Twim::new(p.TWIM1, i2c_pins, twim::Frequency::K100);
let delay = Timer::new(p.TIMER0);
let timer = Timer::new(p.TIMER1);
let mut atecc608a = ATECC608A::new(i2c, delay, timer).unwrap();
// GENKEY COMMAND EXAMPLE
// Note: TFLXTLSConfig has slot 2 configured to hold an ECC private key.
// So, only GENKEY AND PRIVWRITE commands can be used to write (i.e. store or generate private keys) to this slot.
// Check `Slot access policies` section in my GitHub readme for more info.
let slot = 0x02;
let gen_public_key = match atecc608a.atcab_genkey(slot) { // public key retreived upon
Ok(v) => v, // generating and storing a new (random) ECC private key
Err(e) => panic!("Error generating ECC private key: {:?}", e), // in slot 2.
};
let comp_public_key = match atecc608a.atcab_get_pubkey(slot) { // public key computed from
Ok(v) => v, // the previously generated and stored
Err(e) => panic!("Error retrieving ECC public key: {:?}", e), // private key in slot 2.
};
assert_eq!(&gen_public_key[..], &comp_public_key[..]);
loop {}
}
#[exception]
fn HardFault(ef: &cortex_m_rt::ExceptionFrame) -> ! {
panic!("HardFault at {:#?}", ef);
}
#[exception]
fn DefaultHandler(irqn: i16) {
panic!("Unhandled exception (IRQn = {})", irqn);
}
Please see the examples folder for more.
The ATECC608A is a command-based device which receives commands from the system, executes those commands, and then returns a result or error code. It contains an integrated EEPROM storage memory and SRAM buffer. The EEPROM memory contains a total of 1400 bytes and is divided into the following zones:
Before we begin, we'll need to program the Config zone with values that will determine the access policy for how each data slot will respond. The configuration zone can be modified until it has been locked (LockConfig set to !=0x55). In order to enable the access policies, the LockValue byte must be set. Here's a comparison between an out-of-the-box config Vs sample (ATECC-TFLXTLS) config. (Sample config taken from Microchip. It's used in some of its pre-provisioned variants.)
Writing the ATECC-TFLXTLS configuration to the device will yield a personalised device i.e. you can now generate/store keys, certificates and other content in the device's EEPROM slots as shown in the table below. For a more detailed view of slot access policies and commands that can be used on each slot - Detailed slot access policies
Slot | Use-case |
---|---|
0 | Primary private key |
1 | Internal sign private key |
2 | Secondary private key 1 |
3 | Secondary private key 2 |
4 | Secondary private key 3 |
5 | Secret key |
6 | IO protection key |
7 | Secure boot digest |
8 | General data |
9 | AES key |
10 | Device compressed certificate |
11 | Signer public key |
12 | Signer compressed certificate |
13 | Parent public key or general data |
14 | Validated public key |
15 | Secure boot public key |
Important: Please do not proceed before reading this section
atcab_write_config_zone.rs
included in the examples folder.atcab_read_config_zone.rs
to read contents (i.e. all 128 bytes) of config zone. This is just a double check to see if the correct set of bytes (i.e. ATECC-TFLXTLS config bytes) were written to the device.atcab_lock_config_zone_crc.rs
example to lock the config zone. Note: locking the config zone is an irreversible operation. So, please make sure you get everything right before you do.atcab_sign_and_verify.rs
does just that. It generates and loads a new (random) ECC private key into slot 3 of the device. The private key is generated 'within-the-device' and never leaves it. The example contains a test message, which is signed by the private key and verified by the corresponding 'computed' public key.WRITE or GENKEY
will still work without restrictions, even though a slot is configured to be (permanently) not writable.LockValue
of the config zone) are access policies for slots strictly enforced. For example: you can no longer issue the GENKEY command to generate a new random private for slots 0 and 1 but you can issue GENKEY to compute the public key of the corresponding permanent private keys in slots 0 and 1.
Note: I'm yet to implement a method to lock the data zone. I will be adding more commands that will need testing. If you need it, drop a note.
(1) Not all features are implemented, see follow list for details
For questions, issues, feature requests, and other changes, please file an issue in the github project.
Licensed under either of
at your option.
Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in the work by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions.