diff --git a/src/main.rs b/src/main.rs index d56e0d3631bf93972fd52fb52634ef9e384b22c8..b95ebcf79a6371e0ade08d8331b52c332e55fc0b 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,18 +1,23 @@ #![feature(const_fn)] - +#![feature(const_cell_new)] +#![feature(const_unsafe_cell_new)] // The trusted code base, providing services such as Authorization, Encrytion mod trusted { use std::str::from_utf8; + use std::cell::{UnsafeCell, Cell}; + use std::fmt::Debug; + use std::marker::PhantomData; + pub type Key = [u8; 3]; - pub struct Sec { + pub struct Permission { level: u8, } - impl Sec { + impl Permission { pub const unsafe fn new(l: u8) -> Self { - Sec { level: l } + Permission { level: l } } pub fn level(&self) -> u8 { @@ -20,13 +25,10 @@ mod trusted { } } - trait Aut<R, S> { - fn encrypt(aut: Sec, R) -> S; - fn decrypt(aut: Sec, S) -> R; - } - pub fn data_access(sec: &Sec) -> Option<u32> { - if sec.level >= 2 { + + pub fn access(p: &Permission) -> Option<u32> { + if p.level >= 2 { println!("granted"); Some(72) } else { @@ -54,71 +56,237 @@ mod trusted { unsafe { s == CH[CH_NR].1 } } - pub fn auth(key: &Key) -> Sec { - unsafe { if check(key) { Sec::new(2) } else { Sec::new(0) } } + pub fn auth(key: &Key) -> Permission { + unsafe { + if check(key) { + Permission::new(2) + } else { + Permission::new(0) + } + } } } // structure to pass decryptable data - struct Data<T> { - key: Key, + pub struct Data<T> + where + T: Debug, + { + key: Cell<Key>, data: T, } - impl<T> Data<T> { + impl<T> Data<T> + where + T: Debug, + { pub const fn new(d: T) -> Self { Data { - key: [0, 0, 0], + key: Cell::new([0, 0, 0]), data: d, } } // deref ? pub fn get(&self) -> Option<&T> { - if aut::check(&self.key) { + if aut::check(&self.key.get()) { Some(&self.data) } else { None } } + + pub fn set_key(&self, key: Key) -> () { + self.key.set(key); + } } /* impl Aut for Data { - fn encrypt(aut: Sec, R) -> S; - fn decrypt(aut: Sec, S) -> R; + fn encrypt(aut: Permission, R) -> S; + fn decrypt(aut: Permission, S) -> R; } */ + + // simplification of RTFM Resource + pub struct Resource<T> { + data: UnsafeCell<T>, + } + + impl<T> Resource<T> { + pub const fn new(d: T) -> Self { + Resource { data: UnsafeCell::new(d) } + } + pub unsafe fn get(&mut self) -> &mut T { + &mut *self.get() + } + } + + /* + pub struct PmData<'a, T: 'a> { + level: u8, + data: &'a T, + } + + impl<'a, T> PmData<'a, T> + where + T: Debug, + { + pub fn new(d: &'a T, l: u8) -> Self { + PmData { data: d, level: l } + } + + pub fn get(&self, p: Permission) -> Option<&T> { + if p.level() >= self.level { + Some(self.data) + } else { + None + } + } + } + */ + // T the plain type + // str the byte array to store the data + + pub trait Crypto<T> { + fn encrypt(aut: Permission, T, &mut str) -> (); + fn decrypt(aut: Permission, str, &mut T) -> (); + } + + pub struct PmData<T> { + level: u8, + data: T, + } + + impl<T> PmData<T> + where + T: Debug, + { + pub fn new(d: T, l: u8) -> Self { + PmData { data: d, level: l } + } + + pub fn get(&self, p: Permission) -> Option<&T> { + if p.level() >= self.level { + Some(&self.data) + } else { + None + } + } + } + + pub struct Encrypted<T> + where + T: Debug + Crypto<T>, + { + level: u8, + data: T, + } + + impl<T> Encrypted<T> + where + T: Debug + Crypto<T>, + { + pub const fn new(d: T, l: u8) -> Self { + Encrypted { level: l, data: d } + } + + pub unsafe fn get(&mut self) -> &mut T { + &mut *self.get() + } + + pub fn decrypt(&self) -> PmData<String> { + PmData::new(String::from(format!("{:?}", self.data)), self.level) + } + + // pub fn decrypt2(&self) -> PmData<str> { + // PmData::new(format!("{:?}", self.data), self.level) + // } + } + + /* + + //trait Decrypted {} + +pub struct Encrypted<T, D> + where + T: Debug, + D: Decrypted, + { + data: T, + marker: PhantomData<D>, + } + + impl<T, D> Encrypted<T, D> + where + T: Debug, + D: Decrypted, + { + pub const fn new(d: T) -> Self { + Encrypted { + data: d, + marker: PhantomData, + } + } + + pub unsafe fn get(&mut self) -> &mut T { + &mut *self.get() + } + + // not Size + pub fn decrypt(&self) -> &Data<str> { + &Dataformat!("{:?}", self.data) + } + } + }*/ } -static mut U1: u1::State = u1::State::new(); +use trusted::Resource; -static mut U2: u2::State = u2::State::new(); +static mut U1: Resource<u1::State> = Resource::new(u1::State::new()); +static mut U2: Resource<u2::State> = Resource::new(u2::State::new()); // Main should be inside trusted fn main() { println!("trusted base"); - let mut u1 = unsafe { &mut U1 }; - let mut u2 = unsafe { &mut U2 }; + let u1 = unsafe { &mut U1 }; + let u2 = unsafe { &mut U2 }; unsafe { - let s = Sec::new(1); - // s.level = 3; - u1.user1(&s); - u2.user2(&s, &mut u1); // try without key set - u2.enter(&s, "abc"); // - u2.user2(&s, &mut u1); // try with key set - u2.user2(&s, &mut u1); // try with key set - u2.expire(&s); - u2.user2(&s, &mut u1); // try with key set - - u2.enter(&s, "abc"); // - u2.user2(&s, &mut u1); // try with key set - trusted::aut::expire(); - u2.user2(&s, &mut u1); // try with key set - u2.enter(&s, "bcd"); // - u2.user2(&s, &mut u1); // try with key set + let p = Permission::new(1); + let mut u1 = u1.get(); + let mut u2 = u2.get(); + u1.user1(&p); + println!(""); + u2.user2(&p, &mut u1); // try without key set + println!(""); + u2.enter(&p, "abc"); // + println!(""); + u2.user2(&p, &mut u1); // try with key set + println!(""); + u2.user2(&p, &mut u1); // try with key set + println!(""); + u2.expire(&p); + + println!(""); + u2.user2(&p, &mut u1); // try with key set + println!(""); + + u2.enter(&p, "abc"); // + println!(""); + u2.user2(&p, &mut u1); // try with key set, now os call succeed + + println!(""); + trusted::aut::expire(); // os timeout for key + + println!(""); + u2.user2(&p, &mut u1); // try with key set "abc", valid is now "bcd" + + println!(""); + u2.enter(&p, "bcd"); // + println!(""); + u2.user2(&p, &mut u1); // try with key set "bcd" }; } @@ -127,38 +295,46 @@ fn main() { // user code // compiler directive, disallow unsafe code // unsafe constructor new -use trusted::Sec; +use trusted::Permission; use trusted::aut::auth; // - +//mod e1 { +// use ::*; +// +// pub struct State { +// data: u32, +// e: Encrypted<u32>, +// } +// +//} mod u1 { use ::*; - // static sec level + // static Permission level pub struct State { data: u32, - s: &'static Sec, + _s: &'static Permission, } impl State { pub const fn new() -> Self { State { data: 11, - s: &unsafe { Sec::new(1) }, // this would not even be possible + _s: &unsafe { Permission::new(1) }, // this would not even be possible } } - pub fn user1(&mut self, sec: &Sec) { - println!("user1, level = {}", sec.level()); - println!("os call {:?}", trusted::data_access(sec)); + pub fn user1(&mut self, p: &Permission) { + println!("user1, level = {}", p.level()); + println!("os call {:?}", trusted::access(p)); - // self.s = sec; // -- stopped by the borrow checker + // self.s = Permission; // -- stopped by the borrow checker } - pub fn get_data(&mut self, sec: &Sec, p: &Sec) -> Option<u32> { - println!("get_data, level = {}", sec.level()); + pub fn get_data(&mut self, p: &Permission) -> Option<u32> { + println!("get_data, level = {}", p.level()); // self.s = *p; // -- stopped by the borrow checker - println!("os call {:?}", trusted::data_access(p)); + println!("os call {:?}", trusted::access(p)); println!("called by {}", p.level()); if p.level() >= 2 { Some(self.data) @@ -174,11 +350,13 @@ mod u1 { mod u2 { use ::*; use trusted::*; + // use std::slice::bytes; // use std::cmp; pub struct State { key: Key, + data: Data<u32>, } fn copy_slice(dst: &mut [u8], src: &[u8]) -> () { @@ -189,22 +367,29 @@ mod u2 { impl State { pub const fn new() -> Self { - State { key: [0, 0, 0] } + State { + key: [0, 0, 0], + data: Data::new(88), + } } - pub fn user2(&mut self, sec: &Sec, u1: &mut u1::State) { - println!("user2, level = {}", sec.level()); - let s = auth(&self.key); - println!("user2, data = {:?}", u1.get_data(sec, &s)); + // a bit ugly, as u1 is here assumed locked already, but as an example it will do... + pub fn user2(&mut self, p: &Permission, u1: &mut u1::State) { + println!("user2, level = {}", p.level()); + let p1 = auth(&self.key); + println!("user2, access = {:?}", u1.get_data(&p1)); // this will be managed by the CRC-Sec framework + println!("get {:?}", self.data.get()); } - pub fn enter(&mut self, sec: &Sec, k: &str) { - println!("enter, level = {}", sec.level()); + pub fn enter(&mut self, p: &Permission, k: &str) { + println!("enter new key {}, level = {}", k, p.level()); copy_slice(&mut self.key, k.as_bytes()); + self.data.set_key(self.key); } - pub fn expire(&mut self, sec: &Sec) { - println!("enter, level = {}", sec.level()); + pub fn expire(&mut self, p: &Permission) { + println!("enter, level = {}", p.level()); + println!("expire locally stored key"); self.key = [0, 0, 0]; } }