use crate::status::Status;
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
pub enum KeyId {
Nwk = 2,
App = 3,
JsEnc = 4,
JsInt = 5,
GpKe0 = 6,
GpKe1 = 7,
GpKe2 = 8,
GpKe3 = 9,
GpKe4 = 10,
GpKe5 = 11,
AppS = 12,
FNwkSInt = 13,
SNwkSInt = 14,
NwkSEnc = 15,
Rfu0 = 16,
Rfu1 = 17,
McAppS0 = 18,
McAppS1 = 19,
McAppS2 = 20,
McAppS3 = 21,
McNwkS0 = 22,
McNwkS1 = 23,
McNwkS2 = 24,
McNwkS3 = 25,
Gp0 = 26,
Gp1 = 27,
}
impl KeyId {
pub fn is_core(&self) -> bool {
matches!(self, KeyId::Nwk|KeyId::App)
}
pub fn is_lifetime(&self) -> bool {
matches!(self, KeyId::JsEnc|KeyId::JsInt)
}
pub fn is_multicast(&self) -> bool {
matches!(self, KeyId::McAppS0|KeyId::McAppS1|KeyId::McAppS2|KeyId::McAppS3|KeyId::McNwkS0|KeyId::McNwkS1|KeyId::McNwkS2|KeyId::McNwkS3)
}
pub fn is_gp_transport(&self) -> bool {
matches!(self, KeyId::GpKe0|KeyId::GpKe1|KeyId::GpKe2|KeyId::GpKe3|KeyId::GpKe4|KeyId::GpKe5)
}
pub fn is_unicast(&self) -> bool {
matches!(self, KeyId::AppS|KeyId::FNwkSInt|KeyId::SNwkSInt|KeyId::NwkSEnc|KeyId::Rfu0|KeyId::Rfu1)
}
pub fn is_gp(&self) -> bool {
matches!(self, KeyId::Gp0|KeyId::Gp1)
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
pub enum CeStatus {
Success = 0,
FailCmac = 1,
InvKeyId = 3,
BufSize = 5,
Error = 6,
}
impl From<u8> for CeStatus {
fn from(value: u8) -> Self {
match value {
6 => CeStatus::Error,
5 => CeStatus::BufSize,
3 => CeStatus::InvKeyId,
1 => CeStatus::FailCmac,
_ => CeStatus::Success,
}
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
pub enum LorawanVersion {
V1p0 = 0,
V1p1 = 1,
}
pub fn crypto_set_key_req(key_id: KeyId, key: u128) -> [u8; 19] {
let mut cmd = [0u8; 19];
cmd[0] = 0x05;
cmd[1] = 0x02;
cmd[2] |= key_id as u8;
cmd[3] |= ((key >> 120) & 0xFF) as u8;
cmd[4] |= ((key >> 112) & 0xFF) as u8;
cmd[5] |= ((key >> 104) & 0xFF) as u8;
cmd[6] |= ((key >> 96) & 0xFF) as u8;
cmd[7] |= ((key >> 88) & 0xFF) as u8;
cmd[8] |= ((key >> 80) & 0xFF) as u8;
cmd[9] |= ((key >> 72) & 0xFF) as u8;
cmd[10] |= ((key >> 64) & 0xFF) as u8;
cmd[11] |= ((key >> 56) & 0xFF) as u8;
cmd[12] |= ((key >> 48) & 0xFF) as u8;
cmd[13] |= ((key >> 40) & 0xFF) as u8;
cmd[14] |= ((key >> 32) & 0xFF) as u8;
cmd[15] |= ((key >> 24) & 0xFF) as u8;
cmd[16] |= ((key >> 16) & 0xFF) as u8;
cmd[17] |= ((key >> 8) & 0xFF) as u8;
cmd[18] |= (key & 0xFF) as u8;
cmd
}
pub fn crypto_derive_key_req(src_key_id: KeyId, dst_key_id: KeyId, input: u128) -> [u8; 20] {
let mut cmd = [0u8; 20];
cmd[0] = 0x05;
cmd[1] = 0x03;
cmd[2] |= src_key_id as u8;
cmd[3] |= dst_key_id as u8;
cmd[4] |= ((input >> 120) & 0xFF) as u8;
cmd[5] |= ((input >> 112) & 0xFF) as u8;
cmd[6] |= ((input >> 104) & 0xFF) as u8;
cmd[7] |= ((input >> 96) & 0xFF) as u8;
cmd[8] |= ((input >> 88) & 0xFF) as u8;
cmd[9] |= ((input >> 80) & 0xFF) as u8;
cmd[10] |= ((input >> 72) & 0xFF) as u8;
cmd[11] |= ((input >> 64) & 0xFF) as u8;
cmd[12] |= ((input >> 56) & 0xFF) as u8;
cmd[13] |= ((input >> 48) & 0xFF) as u8;
cmd[14] |= ((input >> 40) & 0xFF) as u8;
cmd[15] |= ((input >> 32) & 0xFF) as u8;
cmd[16] |= ((input >> 24) & 0xFF) as u8;
cmd[17] |= ((input >> 16) & 0xFF) as u8;
cmd[18] |= ((input >> 8) & 0xFF) as u8;
cmd[19] |= (input & 0xFF) as u8;
cmd
}
pub fn crypto_process_join_accept_req(dec_key_id: KeyId, ver_key_id: KeyId, lorawan_version: LorawanVersion) -> [u8; 5] {
let mut cmd = [0u8; 5];
cmd[0] = 0x05;
cmd[1] = 0x04;
cmd[2] |= dec_key_id as u8;
cmd[3] |= ver_key_id as u8;
cmd[4] |= lorawan_version as u8;
cmd
}
pub fn crypto_compute_aes_cmac_req(key_id: KeyId) -> [u8; 3] {
let mut cmd = [0u8; 3];
cmd[0] = 0x05;
cmd[1] = 0x05;
cmd[2] |= key_id as u8;
cmd
}
pub fn crypto_verify_aes_cmac_req(key_id: KeyId, expected_mic: u32) -> [u8; 7] {
let mut cmd = [0u8; 7];
cmd[0] = 0x05;
cmd[1] = 0x06;
cmd[2] |= key_id as u8;
cmd[3] |= ((expected_mic >> 24) & 0xFF) as u8;
cmd[4] |= ((expected_mic >> 16) & 0xFF) as u8;
cmd[5] |= ((expected_mic >> 8) & 0xFF) as u8;
cmd[6] |= (expected_mic & 0xFF) as u8;
cmd
}
pub fn crypto_aes_encrypt01_req(key_id: KeyId) -> [u8; 3] {
let mut cmd = [0u8; 3];
cmd[0] = 0x05;
cmd[1] = 0x07;
cmd[2] |= key_id as u8;
cmd
}
pub fn crypto_aes_encrypt_req(key_id: KeyId) -> [u8; 3] {
let mut cmd = [0u8; 3];
cmd[0] = 0x05;
cmd[1] = 0x08;
cmd[2] |= key_id as u8;
cmd
}
pub fn crypto_aes_decrypt_req(key_id: KeyId) -> [u8; 3] {
let mut cmd = [0u8; 3];
cmd[0] = 0x05;
cmd[1] = 0x09;
cmd[2] |= key_id as u8;
cmd
}
pub fn crypto_store_to_flash_req() -> [u8; 2] {
[0x05, 0x0A]
}
pub fn crypto_restore_from_flash_req() -> [u8; 2] {
[0x05, 0x0B]
}
pub fn crypto_set_param_req(param_id: u8, data: u32) -> [u8; 7] {
let mut cmd = [0u8; 7];
cmd[0] = 0x05;
cmd[1] = 0x0D;
cmd[2] |= param_id;
cmd[3] |= ((data >> 24) & 0xFF) as u8;
cmd[4] |= ((data >> 16) & 0xFF) as u8;
cmd[5] |= ((data >> 8) & 0xFF) as u8;
cmd[6] |= (data & 0xFF) as u8;
cmd
}
pub fn crypto_get_param_req(param_id: u8) -> [u8; 3] {
let mut cmd = [0u8; 3];
cmd[0] = 0x05;
cmd[1] = 0x0E;
cmd[2] |= param_id;
cmd
}
pub fn crypto_check_encrypted_firmware_image_cmd(offset: u32) -> [u8; 6] {
let mut cmd = [0u8; 6];
cmd[0] = 0x05;
cmd[1] = 0x0F;
cmd[2] |= ((offset >> 24) & 0xFF) as u8;
cmd[3] |= ((offset >> 16) & 0xFF) as u8;
cmd[4] |= ((offset >> 8) & 0xFF) as u8;
cmd[5] |= (offset & 0xFF) as u8;
cmd
}
pub fn crypto_check_encrypted_firmware_image_result_req() -> [u8; 2] {
[0x05, 0x10]
}
#[derive(Default)]
pub struct CryptoSetKeyRsp([u8; 2]);
impl CryptoSetKeyRsp {
pub fn new() -> Self {
Self::default()
}
pub fn status(&mut self) -> Status {
self.0[0].into()
}
pub fn ce_status(&self) -> CeStatus {
self.0[1].into()
}
}
impl AsMut<[u8]> for CryptoSetKeyRsp {
fn as_mut(&mut self) -> &mut [u8] {
&mut self.0
}
}
#[derive(Default)]
pub struct CryptoDeriveKeyRsp([u8; 2]);
impl CryptoDeriveKeyRsp {
pub fn new() -> Self {
Self::default()
}
pub fn status(&mut self) -> Status {
self.0[0].into()
}
pub fn ce_status(&self) -> CeStatus {
self.0[1].into()
}
}
impl AsMut<[u8]> for CryptoDeriveKeyRsp {
fn as_mut(&mut self) -> &mut [u8] {
&mut self.0
}
}
#[derive(Default)]
pub struct CryptoProcessJoinAcceptRsp([u8; 2]);
impl CryptoProcessJoinAcceptRsp {
pub fn new() -> Self {
Self::default()
}
pub fn status(&mut self) -> Status {
self.0[0].into()
}
pub fn ce_status(&self) -> CeStatus {
self.0[1].into()
}
}
impl AsMut<[u8]> for CryptoProcessJoinAcceptRsp {
fn as_mut(&mut self) -> &mut [u8] {
&mut self.0
}
}
#[derive(Default)]
pub struct CryptoComputeAesCmacRsp([u8; 6]);
impl CryptoComputeAesCmacRsp {
pub fn new() -> Self {
Self::default()
}
pub fn status(&mut self) -> Status {
self.0[0].into()
}
pub fn ce_status(&self) -> CeStatus {
self.0[1].into()
}
pub fn mic(&self) -> u32 {
(self.0[5] as u32) |
((self.0[4] as u32) << 8) |
((self.0[3] as u32) << 16) |
((self.0[2] as u32) << 24)
}
}
impl AsMut<[u8]> for CryptoComputeAesCmacRsp {
fn as_mut(&mut self) -> &mut [u8] {
&mut self.0
}
}
#[derive(Default)]
pub struct CryptoVerifyAesCmacRsp([u8; 2]);
impl CryptoVerifyAesCmacRsp {
pub fn new() -> Self {
Self::default()
}
pub fn status(&mut self) -> Status {
self.0[0].into()
}
pub fn ce_status(&self) -> CeStatus {
self.0[1].into()
}
}
impl AsMut<[u8]> for CryptoVerifyAesCmacRsp {
fn as_mut(&mut self) -> &mut [u8] {
&mut self.0
}
}
#[derive(Default)]
pub struct CryptoAesEncrypt01Rsp([u8; 2]);
impl CryptoAesEncrypt01Rsp {
pub fn new() -> Self {
Self::default()
}
pub fn status(&mut self) -> Status {
self.0[0].into()
}
pub fn ce_status(&self) -> CeStatus {
self.0[1].into()
}
}
impl AsMut<[u8]> for CryptoAesEncrypt01Rsp {
fn as_mut(&mut self) -> &mut [u8] {
&mut self.0
}
}
#[derive(Default)]
pub struct CryptoAesEncryptRsp([u8; 2]);
impl CryptoAesEncryptRsp {
pub fn new() -> Self {
Self::default()
}
pub fn status(&mut self) -> Status {
self.0[0].into()
}
pub fn ce_status(&self) -> CeStatus {
self.0[1].into()
}
}
impl AsMut<[u8]> for CryptoAesEncryptRsp {
fn as_mut(&mut self) -> &mut [u8] {
&mut self.0
}
}
#[derive(Default)]
pub struct CryptoAesDecryptRsp([u8; 2]);
impl CryptoAesDecryptRsp {
pub fn new() -> Self {
Self::default()
}
pub fn status(&mut self) -> Status {
self.0[0].into()
}
pub fn ce_status(&self) -> CeStatus {
self.0[1].into()
}
}
impl AsMut<[u8]> for CryptoAesDecryptRsp {
fn as_mut(&mut self) -> &mut [u8] {
&mut self.0
}
}
#[derive(Default)]
pub struct CryptoStoreToFlashRsp([u8; 2]);
impl CryptoStoreToFlashRsp {
pub fn new() -> Self {
Self::default()
}
pub fn status(&mut self) -> Status {
self.0[0].into()
}
pub fn ce_status(&self) -> CeStatus {
self.0[1].into()
}
}
impl AsMut<[u8]> for CryptoStoreToFlashRsp {
fn as_mut(&mut self) -> &mut [u8] {
&mut self.0
}
}
#[derive(Default)]
pub struct CryptoRestoreFromFlashRsp([u8; 2]);
impl CryptoRestoreFromFlashRsp {
pub fn new() -> Self {
Self::default()
}
pub fn status(&mut self) -> Status {
self.0[0].into()
}
pub fn ce_status(&self) -> CeStatus {
self.0[1].into()
}
}
impl AsMut<[u8]> for CryptoRestoreFromFlashRsp {
fn as_mut(&mut self) -> &mut [u8] {
&mut self.0
}
}
#[derive(Default)]
pub struct CryptoSetParamRsp([u8; 2]);
impl CryptoSetParamRsp {
pub fn new() -> Self {
Self::default()
}
pub fn status(&mut self) -> Status {
self.0[0].into()
}
pub fn ce_status(&self) -> CeStatus {
self.0[1].into()
}
}
impl AsMut<[u8]> for CryptoSetParamRsp {
fn as_mut(&mut self) -> &mut [u8] {
&mut self.0
}
}
#[derive(Default)]
pub struct CryptoGetParamRsp([u8; 6]);
impl CryptoGetParamRsp {
pub fn new() -> Self {
Self::default()
}
pub fn status(&mut self) -> Status {
self.0[0].into()
}
pub fn ce_status(&self) -> CeStatus {
self.0[1].into()
}
pub fn data(&self) -> u32 {
(self.0[5] as u32) |
((self.0[4] as u32) << 8) |
((self.0[3] as u32) << 16) |
((self.0[2] as u32) << 24)
}
}
impl AsMut<[u8]> for CryptoGetParamRsp {
fn as_mut(&mut self) -> &mut [u8] {
&mut self.0
}
}
#[derive(Default)]
pub struct CryptoCheckEncryptedFirmwareImageResultRsp([u8; 2]);
impl CryptoCheckEncryptedFirmwareImageResultRsp {
pub fn new() -> Self {
Self::default()
}
pub fn status(&mut self) -> Status {
self.0[0].into()
}
pub fn success(&self) -> bool {
self.0[1] & 0x1 != 0
}
}
impl AsMut<[u8]> for CryptoCheckEncryptedFirmwareImageResultRsp {
fn as_mut(&mut self) -> &mut [u8] {
&mut self.0
}
}