use lib_q_aead::security::validation::{
validate_key,
validate_nonce,
};
use lib_q_aead::{
AeadKey,
AeadWithMetadata,
Algorithm,
Nonce,
create_aead,
};
fn main() -> Result<(), Box<dyn std::error::Error>> {
println!("lib-q-aead No-Std Example");
println!("=========================");
embedded_main().map_err(|e| e.into())
}
fn embedded_main() -> Result<(), &'static str> {
let aead = create_aead(Algorithm::Shake256Aead).map_err(|_| "Failed to create AEAD")?;
let key_data = [
0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF, 0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32,
0x10, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xAA, 0xBB, 0xCC, 0xDD, 0xEE,
0xFF, 0x00,
];
let nonce_data = [
0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF, 0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32,
0x10,
];
validate_key(&key_data).map_err(|_| "Invalid key")?;
validate_nonce(&nonce_data).map_err(|_| "Invalid nonce")?;
let key = AeadKey::new(key_data.to_vec());
let nonce = Nonce::new(nonce_data.to_vec());
let sensor_data = b"Sensor reading: 25.3C, Humidity: 60%";
let _metadata = b"device_id: 0x1234, timestamp: 1234567890";
println!("🔧 Simulating embedded system operations...");
println!("📁 Testing flash memory operations...");
let flash_address = 0x1000;
embedded_usage::store_encrypted_data(&*aead, &key, &nonce, sensor_data, flash_address)?;
println!("✓ Encrypted data stored in flash memory");
let decrypted_from_flash =
embedded_usage::load_encrypted_data(&*aead, &key, &nonce, flash_address, 1024)?;
println!("✓ Data loaded and decrypted from flash memory");
if decrypted_from_flash != sensor_data {
return Err("Flash memory data integrity check failed");
}
println!("✓ Flash memory data integrity verified");
println!("📡 Testing UART communication...");
embedded_usage::send_secure_message(&*aead, &key, &nonce, b"Hello from embedded device!")?;
println!("✓ Secure message sent over UART");
let mut receive_buffer = [0u8; 64];
let received_message =
embedded_usage::receive_secure_message(&*aead, &key, &nonce, &mut receive_buffer)?;
println!("✓ Secure message received and decrypted from UART");
println!(" Received: {}", String::from_utf8_lossy(&received_message));
println!("💾 Testing memory-efficient operations...");
let large_data = b"This is a large piece of data that needs to be processed in chunks to minimize memory usage in embedded systems.";
let chunked_result =
constrained_usage::process_large_data_in_chunks(&*aead, &key, &nonce, large_data, 32)?;
println!(
"✓ Large data processed in chunks ({} bytes)",
chunked_result.len()
);
let stack_buffer =
constrained_usage::encrypt_with_stack_buffer(&*aead, &key, &nonce, b"Stack buffer test")?;
println!("✓ Data encrypted using stack-allocated buffer");
let actual_length = stack_buffer
.iter()
.position(|&b| b == 0)
.unwrap_or(stack_buffer.len());
let actual_ciphertext = &stack_buffer[..actual_length];
let decrypted_stack = aead
.decrypt(&key, &nonce, actual_ciphertext, None)
.map_err(|_| "Stack buffer decryption failed")?;
if decrypted_stack != b"Stack buffer test" {
return Err("Stack buffer data integrity check failed");
}
println!("✓ Stack buffer data integrity verified");
println!("⚠️ Testing comprehensive error handling...");
println!("🔍 Testing FlashError variants...");
match embedded_hal::FlashMemory::write(0, &[]) {
Err(embedded_hal::FlashError::InvalidAddress) => {
println!("✓ FlashError::InvalidAddress works correctly")
}
_ => println!("⚠️ Unexpected flash error behavior"),
}
match embedded_hal::FlashMemory::write(0xFFFF, b"test") {
Err(embedded_hal::FlashError::WriteProtection) => {
println!("✓ FlashError::WriteProtection works correctly")
}
_ => println!("⚠️ Unexpected flash error behavior"),
}
match embedded_hal::FlashMemory::write(0xFFFE, b"test") {
Err(embedded_hal::FlashError::EraseFailure) => {
println!("✓ FlashError::EraseFailure works correctly")
}
_ => println!("⚠️ Unexpected flash error behavior"),
}
match embedded_hal::FlashMemory::write(0xFFFD, b"test") {
Err(embedded_hal::FlashError::ProgramFailure) => {
println!("✓ FlashError::ProgramFailure works correctly")
}
_ => println!("⚠️ Unexpected flash error behavior"),
}
match embedded_hal::FlashMemory::write(0xFFFC, b"test") {
Err(embedded_hal::FlashError::VerifyFailure) => {
println!("✓ FlashError::VerifyFailure works correctly")
}
_ => println!("⚠️ Unexpected flash error behavior"),
}
println!("🔍 Testing UartError variants...");
match embedded_hal::Uart::send(&[]) {
Err(embedded_hal::UartError::EmptyBuffer) => {
println!("✓ UartError::EmptyBuffer works correctly")
}
_ => println!("⚠️ Unexpected UART error behavior"),
}
let large_data = vec![0u8; 1001]; match embedded_hal::Uart::send(&large_data) {
Err(embedded_hal::UartError::TransmissionError) => {
println!("✓ UartError::TransmissionError works correctly")
}
_ => println!("⚠️ Unexpected UART error behavior"),
}
match embedded_hal::Uart::send(&[0xFF, 0x01, 0x02]) {
Err(embedded_hal::UartError::Timeout) => {
println!("✓ UartError::Timeout works correctly")
}
_ => println!("⚠️ Unexpected UART error behavior"),
}
let mut large_buffer = vec![0u8; 1001]; match embedded_hal::Uart::receive(&mut large_buffer) {
Err(embedded_hal::UartError::ReceptionError) => {
println!("✓ UartError::ReceptionError works correctly")
}
_ => println!("⚠️ Unexpected UART error behavior"),
}
println!("🎉 All embedded system operations completed successfully!");
println!(" - Flash memory operations: ✓");
println!(" - UART communication: ✓");
println!(" - Memory-efficient processing: ✓");
println!(" - Error handling: ✓");
Ok(())
}
mod embedded_hal {
use core::result::Result;
#[allow(clippy::disallowed_types)]
use std::collections::HashMap;
use std::sync::{
LazyLock,
Mutex,
};
#[allow(clippy::disallowed_types)]
static FLASH_STORAGE: LazyLock<Mutex<HashMap<usize, Vec<u8>>>> =
LazyLock::new(|| Mutex::new(HashMap::new()));
pub struct FlashMemory;
impl FlashMemory {
pub fn write(address: usize, data: &[u8]) -> Result<(), FlashError> {
if address == 0 || data.is_empty() {
return Err(FlashError::InvalidAddress);
}
if address == 0xFFFF {
return Err(FlashError::WriteProtection);
}
if address == 0xFFFE {
return Err(FlashError::EraseFailure);
}
if address == 0xFFFD {
return Err(FlashError::ProgramFailure);
}
if address == 0xFFFC {
return Err(FlashError::VerifyFailure);
}
if let Ok(mut storage) = FLASH_STORAGE.lock() {
storage.insert(address, data.to_vec());
}
Ok(())
}
pub fn read(address: usize, _length: usize) -> Result<Vec<u8>, FlashError> {
if address == 0 {
return Err(FlashError::InvalidAddress);
}
if let Ok(storage) = FLASH_STORAGE.lock() &&
let Some(data) = storage.get(&address)
{
return Ok(data.clone());
}
Ok(Vec::new())
}
}
static UART_BUFFER: LazyLock<Mutex<Vec<u8>>> = LazyLock::new(|| Mutex::new(Vec::new()));
pub struct Uart;
impl Uart {
pub fn send(data: &[u8]) -> Result<(), UartError> {
if data.is_empty() {
return Err(UartError::EmptyBuffer);
}
if data.len() > 1000 {
return Err(UartError::TransmissionError);
}
if data[0] == 0xFF {
return Err(UartError::Timeout);
}
if let Ok(mut buffer) = UART_BUFFER.lock() {
buffer.clear();
buffer.extend_from_slice(data);
}
for &_byte in data {
for _ in 0..100 {
core::hint::spin_loop();
}
}
Ok(())
}
pub fn receive(buffer: &mut [u8]) -> Result<&[u8], UartError> {
if buffer.is_empty() {
return Err(UartError::EmptyBuffer);
}
if buffer.len() > 1000 {
return Err(UartError::ReceptionError);
}
if let Ok(uart_buffer) = UART_BUFFER.lock() {
let received_length = buffer.len().min(uart_buffer.len());
if received_length > 0 {
buffer[..received_length].copy_from_slice(&uart_buffer[..received_length]);
return Ok(&buffer[..received_length]);
}
}
Ok(&buffer[..0])
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum FlashError {
InvalidAddress,
WriteProtection,
EraseFailure,
ProgramFailure,
VerifyFailure,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum UartError {
EmptyBuffer,
TransmissionError,
ReceptionError,
Timeout,
}
}
mod embedded_usage {
use embedded_hal::{
FlashMemory,
Uart,
};
use super::*;
pub fn store_encrypted_data(
aead: &dyn AeadWithMetadata,
key: &AeadKey,
nonce: &Nonce,
data: &[u8],
flash_address: usize,
) -> Result<(), &'static str> {
let ciphertext = aead
.encrypt(key, nonce, data, None)
.map_err(|_| "Encryption failed")?;
FlashMemory::write(flash_address, &ciphertext).map_err(|_| "Flash write failed")?;
Ok(())
}
pub fn load_encrypted_data(
aead: &dyn AeadWithMetadata,
key: &AeadKey,
nonce: &Nonce,
flash_address: usize,
_length: usize,
) -> Result<Vec<u8>, &'static str> {
let ciphertext = FlashMemory::read(flash_address, 0).map_err(|_| "Flash read failed")?;
if ciphertext.is_empty() {
return Err("No data found in flash memory");
}
let decrypted = aead
.decrypt(key, nonce, &ciphertext, None)
.map_err(|_| "Decryption failed")?;
Ok(decrypted)
}
pub fn send_secure_message(
aead: &dyn AeadWithMetadata,
key: &AeadKey,
nonce: &Nonce,
message: &[u8],
) -> Result<(), &'static str> {
let ciphertext = aead
.encrypt(key, nonce, message, None)
.map_err(|_| "Encryption failed")?;
Uart::send(&ciphertext).map_err(|_| "UART send failed")?;
Ok(())
}
pub fn receive_secure_message(
aead: &dyn AeadWithMetadata,
key: &AeadKey,
nonce: &Nonce,
buffer: &mut [u8],
) -> Result<Vec<u8>, &'static str> {
let received = Uart::receive(buffer).map_err(|_| "UART receive failed")?;
let decrypted = aead
.decrypt(key, nonce, received, None)
.map_err(|_| "Decryption failed")?;
Ok(decrypted)
}
}
mod constrained_usage {
use super::*;
pub fn process_large_data_in_chunks(
aead: &dyn AeadWithMetadata,
key: &AeadKey,
nonce: &Nonce,
data: &[u8],
chunk_size: usize,
) -> Result<Vec<u8>, &'static str> {
let mut result = Vec::new();
for chunk in data.chunks(chunk_size) {
let ciphertext = aead
.encrypt(key, nonce, chunk, None)
.map_err(|_| "Encryption failed")?;
result.extend_from_slice(&ciphertext);
}
Ok(result)
}
pub fn encrypt_with_stack_buffer(
aead: &dyn AeadWithMetadata,
key: &AeadKey,
nonce: &Nonce,
data: &[u8],
) -> Result<[u8; 1024], &'static str> {
let mut buffer = [0u8; 1024];
let ciphertext = aead
.encrypt(key, nonce, data, None)
.map_err(|_| "Encryption failed")?;
if ciphertext.len() > buffer.len() {
return Err("Ciphertext too large for buffer");
}
buffer[..ciphertext.len()].copy_from_slice(&ciphertext);
Ok(buffer)
}
}