use core::convert::TryInto;
use ed25519_compact::{KeyPair, PublicKey, Seed, Signature};
use heapless::spsc::Queue;
use crate::{BleAdvertiser, Entropy, LoraRadio, NfcReader, SecureElement};
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum MockError {
Empty,
BufferTooSmall,
OutboxFull,
BadSeed,
Rng,
}
pub const MOCK_FRAME_CAP: usize = 1024;
pub const MOCK_QUEUE_CAP: usize = 16;
#[derive(Debug)]
pub struct MockLoraRadio {
pub inbox: heapless::Vec<heapless::Vec<u8, MOCK_FRAME_CAP>, MOCK_QUEUE_CAP>,
pub outbox: heapless::Vec<heapless::Vec<u8, MOCK_FRAME_CAP>, MOCK_QUEUE_CAP>,
}
impl Default for MockLoraRadio {
fn default() -> Self {
Self::new()
}
}
impl MockLoraRadio {
pub fn new() -> Self {
MockLoraRadio {
inbox: heapless::Vec::new(),
outbox: heapless::Vec::new(),
}
}
pub fn enqueue_inbox(&mut self, frame: &[u8]) -> Result<(), MockError> {
let mut v: heapless::Vec<u8, MOCK_FRAME_CAP> = heapless::Vec::new();
v.extend_from_slice(frame)
.map_err(|_| MockError::BufferTooSmall)?;
self.inbox.push(v).map_err(|_| MockError::OutboxFull)?;
Ok(())
}
}
impl LoraRadio for MockLoraRadio {
type Error = MockError;
fn send(&mut self, payload: &[u8]) -> Result<(), Self::Error> {
let mut v: heapless::Vec<u8, MOCK_FRAME_CAP> = heapless::Vec::new();
v.extend_from_slice(payload)
.map_err(|_| MockError::BufferTooSmall)?;
self.outbox.push(v).map_err(|_| MockError::OutboxFull)?;
Ok(())
}
fn recv(&mut self, buf: &mut [u8]) -> Result<usize, Self::Error> {
if self.inbox.is_empty() {
return Err(MockError::Empty);
}
let frame = self.inbox.remove(0);
if frame.len() > buf.len() {
return Err(MockError::BufferTooSmall);
}
buf[..frame.len()].copy_from_slice(&frame);
Ok(frame.len())
}
}
#[derive(Debug)]
pub struct MockBleAdvertiser {
pub last: Option<heapless::Vec<u8, MOCK_FRAME_CAP>>,
pub advertise_count: u32,
}
impl Default for MockBleAdvertiser {
fn default() -> Self {
Self::new()
}
}
impl MockBleAdvertiser {
pub fn new() -> Self {
MockBleAdvertiser {
last: None,
advertise_count: 0,
}
}
}
impl BleAdvertiser for MockBleAdvertiser {
type Error = MockError;
fn advertise(&mut self, payload: &[u8]) -> Result<(), Self::Error> {
let mut v: heapless::Vec<u8, MOCK_FRAME_CAP> = heapless::Vec::new();
v.extend_from_slice(payload)
.map_err(|_| MockError::BufferTooSmall)?;
self.last = Some(v);
self.advertise_count += 1;
Ok(())
}
}
#[derive(Debug)]
pub struct MockNfcReader {
pub queue: heapless::Vec<heapless::Vec<u8, MOCK_FRAME_CAP>, MOCK_QUEUE_CAP>,
}
impl Default for MockNfcReader {
fn default() -> Self {
Self::new()
}
}
impl MockNfcReader {
pub fn new() -> Self {
MockNfcReader {
queue: heapless::Vec::new(),
}
}
pub fn enqueue(&mut self, frame: &[u8]) -> Result<(), MockError> {
let mut v: heapless::Vec<u8, MOCK_FRAME_CAP> = heapless::Vec::new();
v.extend_from_slice(frame)
.map_err(|_| MockError::BufferTooSmall)?;
self.queue.push(v).map_err(|_| MockError::OutboxFull)?;
Ok(())
}
}
impl NfcReader for MockNfcReader {
type Error = MockError;
fn read(&mut self, buf: &mut [u8]) -> Result<usize, Self::Error> {
if self.queue.is_empty() {
return Err(MockError::Empty);
}
let frame = self.queue.remove(0);
if frame.len() > buf.len() {
return Err(MockError::BufferTooSmall);
}
buf[..frame.len()].copy_from_slice(&frame);
Ok(frame.len())
}
}
#[derive(Debug)]
pub struct MockSecureElement {
keypair: KeyPair,
pub_bytes: [u8; 32],
}
impl MockSecureElement {
pub fn from_seed(seed_bytes: [u8; 32]) -> Result<Self, MockError> {
let seed = Seed::from_slice(&seed_bytes).map_err(|_| MockError::BadSeed)?;
let keypair = KeyPair::from_seed(seed);
let pub_bytes: [u8; 32] = keypair
.pk
.as_ref()
.try_into()
.map_err(|_| MockError::BadSeed)?;
Ok(MockSecureElement { keypair, pub_bytes })
}
pub fn verify(&self, msg: &[u8], sig: &[u8; 64]) -> bool {
let sig = match Signature::from_slice(sig) {
Ok(s) => s,
Err(_) => return false,
};
let pk = match PublicKey::from_slice(&self.pub_bytes) {
Ok(p) => p,
Err(_) => return false,
};
pk.verify(msg, &sig).is_ok()
}
}
impl SecureElement for MockSecureElement {
type Error = MockError;
fn sign(&mut self, msg: &[u8]) -> Result<[u8; 64], Self::Error> {
let sig = self.keypair.sk.sign(msg, None);
let bytes: [u8; 64] = sig.as_ref().try_into().expect("ed25519 sig is 64 bytes");
Ok(bytes)
}
fn pubkey(&self) -> [u8; 32] {
self.pub_bytes
}
}
#[derive(Debug)]
pub struct MockEntropy {
state: u64,
}
impl MockEntropy {
pub fn new(seed: u64) -> Self {
let s = if seed == 0 {
0xdead_beef_dead_beef
} else {
seed
};
MockEntropy { state: s }
}
}
impl Entropy for MockEntropy {
type Error = MockError;
fn fill(&mut self, buf: &mut [u8]) -> Result<(), Self::Error> {
for chunk in buf.chunks_mut(8) {
self.state ^= self.state << 13;
self.state ^= self.state >> 7;
self.state ^= self.state << 17;
let v = self.state.wrapping_mul(0x2545_F491_4F6C_DD1Du64);
let bytes = v.to_le_bytes();
chunk.copy_from_slice(&bytes[..chunk.len()]);
}
Ok(())
}
}
#[doc(hidden)]
pub type _UnusedQueueImport<T, const N: usize> = Queue<T, N>;