use embassy_time::Duration;
use embedded_hal::digital::OutputPin;
use embedded_hal_async::spi::SpiBus;
use super::{BusyPin, Lr1120, Lr1120Error};
pub use crate::cmd::cmd_crypto::*;
#[derive(Debug, Clone)]
pub struct CeDataRes<'a> {
pub status: CeStatus,
pub data: &'a [u8],
}
impl<O,SPI, M> Lr1120<O,SPI, M> where
O: OutputPin, SPI: SpiBus<u8>, M: BusyPin
{
pub async fn ce_set_key(&mut self, id: KeyId, key: u128) -> Result<CeStatus, Lr1120Error> {
let req = crypto_set_key_req(id, key);
let mut rsp = CryptoSetKeyRsp::new();
self.cmd_rd(&req, rsp.as_mut()).await?;
Ok(rsp.ce_status())
}
pub async fn ce_derive_key(&mut self, src: KeyId, dst: KeyId, input: u128) -> Result<CeStatus, Lr1120Error> {
if !src.is_core() && !src.is_gp_transport() {
return Err(Lr1120Error::InvalidParam);
}
if dst.is_core() {
return Err(Lr1120Error::InvalidParam);
}
let req = crypto_derive_key_req(src, dst, input);
let mut rsp = CryptoDeriveKeyRsp::new();
self.cmd_rd(&req, rsp.as_mut()).await?;
Ok(rsp.ce_status())
}
pub async fn ce_process_join_accept(&'_ mut self, dec: KeyId, mic: KeyId, lorawan: LorawanVersion, data: &[u8]) -> Result<CeDataRes<'_>, Lr1120Error> {
let hdr_len = match lorawan {
LorawanVersion::V1p0 => 1,
LorawanVersion::V1p1 => 12,
};
let rsp_len = data.len().saturating_sub(hdr_len);
if rsp_len != 16 && rsp_len!=32 {
return Err(Lr1120Error::InvalidParam);
}
let req = crypto_process_join_accept_req(dec, mic, lorawan);
self.cmd_data_wr(&req, data).await?;
self.wait_ready(Duration::from_millis(100)).await?;
self.rsp_rd(rsp_len).await?;
let status : CeStatus = self.buffer()[0].into();
let payload = &self.buffer()[1..rsp_len+1];
Ok(CeDataRes{status, data:payload})
}
pub async fn ce_compute_cmac(&mut self, key: KeyId, data: &[u8]) -> Result<CryptoComputeAesCmacRsp, Lr1120Error> {
if key!=KeyId::Nwk && key!=KeyId::JsInt && !key.is_unicast() {
return Err(Lr1120Error::InvalidParam);
}
let req = crypto_compute_aes_cmac_req(key);
self.cmd_data_wr(&req, data).await?;
let mut rsp = CryptoComputeAesCmacRsp::new();
self.rsp_rd_to(rsp.as_mut()).await?;
Ok(rsp)
}
pub async fn ce_verify_cmac(&mut self, key: KeyId, mic: u32, data: &[u8]) -> Result<CeStatus, Lr1120Error> {
if key!=KeyId::Nwk && key!=KeyId::JsInt && !key.is_unicast() && !key.is_multicast() {
return Err(Lr1120Error::InvalidParam);
}
let req = crypto_verify_aes_cmac_req(key, mic);
self.cmd_data_wr(&req, data).await?;
let mut rsp = CryptoVerifyAesCmacRsp::new();
self.rsp_rd_to(rsp.as_mut()).await?;
Ok(rsp.ce_status())
}
pub async fn ce_encrypt_lorawan(&'_ mut self, key: KeyId, din: &[u8]) -> Result<CeDataRes<'_>, Lr1120Error> {
if !key.is_unicast() && !key.is_multicast() {
return Err(Lr1120Error::InvalidParam);
}
let req = crypto_aes_encrypt01_req(key);
self.cmd_data_wr(&req, din).await?;
let rsp_len = din.len() + 1;
self.rsp_rd(rsp_len).await?;
let status : CeStatus = self.buffer()[0].into();
let data = &self.buffer()[1..rsp_len];
Ok(CeDataRes{status, data})
}
pub async fn ce_encrypt(&'_ mut self, key: KeyId, din: &[u8]) -> Result<CeDataRes<'_>, Lr1120Error> {
let req = crypto_aes_encrypt_req(key);
self.cmd_data_wr(&req, din).await?;
let rsp_len = din.len() + 1;
self.rsp_rd(rsp_len).await?;
let status : CeStatus = self.buffer()[0].into();
let data = &self.buffer()[1..rsp_len];
Ok(CeDataRes{status, data})
}
pub async fn ce_decrypt(&'_ mut self, key: KeyId, din: &[u8]) -> Result<CeDataRes<'_>, Lr1120Error> {
let req = crypto_aes_decrypt_req(key);
self.cmd_data_wr(&req, din).await?;
let rsp_len = din.len() + 1;
self.rsp_rd(rsp_len).await?;
let status : CeStatus = self.buffer()[0].into();
let data = &self.buffer()[1..rsp_len];
Ok(CeDataRes{status, data})
}
pub async fn ce_store_to_flash(&mut self) -> Result<CeStatus, Lr1120Error> {
let req = crypto_store_to_flash_req();
let mut rsp = CryptoStoreToFlashRsp::new();
self.cmd_rd(&req, rsp.as_mut()).await?;
Ok(rsp.ce_status())
}
pub async fn ce_restore_from_flash(&mut self) -> Result<CeStatus, Lr1120Error> {
let req = crypto_restore_from_flash_req();
let mut rsp = CryptoRestoreFromFlashRsp::new();
self.cmd_rd(&req, rsp.as_mut()).await?;
Ok(rsp.ce_status())
}
pub async fn ce_set_param(&mut self, id: u8, value: u32) -> Result<CeStatus, Lr1120Error> {
let req = crypto_set_param_req(id, value);
let mut rsp = CryptoSetParamRsp::new();
self.cmd_rd(&req, rsp.as_mut()).await?;
Ok(rsp.ce_status())
}
pub async fn ce_get_param(&mut self, id: u8) -> Result<CryptoGetParamRsp, Lr1120Error> {
let req = crypto_get_param_req(id);
let mut rsp = CryptoGetParamRsp::new();
self.cmd_rd(&req, rsp.as_mut()).await?;
Ok(rsp)
}
pub async fn ce_check_fw_image(&mut self, offset: u32, data: &[u8]) -> Result<(), Lr1120Error> {
let req = crypto_check_encrypted_firmware_image_cmd(offset);
self.cmd_data_wr(&req, data).await
}
pub async fn ce_fw_image_ok(&mut self) -> Result<bool, Lr1120Error> {
let req = crypto_check_encrypted_firmware_image_result_req();
let mut rsp = CryptoCheckEncryptedFirmwareImageResultRsp::new();
self.cmd_rd(&req, rsp.as_mut()).await?;
Ok(rsp.success())
}
}