Change the implementation of various traites to ensure test_single is low overhead

This commit is contained in:
Guillume DIDIER 2021-07-21 10:20:13 +02:00
parent 2d179897bf
commit 19b07d1b1f
5 changed files with 231 additions and 20 deletions

View File

@ -88,7 +88,7 @@ pub unsafe fn attack_t_tables_poc<T: ChannelHandle>(
addresses.shuffle(&mut thread_rng()); addresses.shuffle(&mut thread_rng());
let mut victims_handle = unsafe { side_channel.calibrate(addresses.clone()).unwrap() }; let mut victims_handle = unsafe { side_channel.tcalibrate(addresses.clone()).unwrap() };
for addr in addresses.iter() { for addr in addresses.iter() {
let mut timing = HashMap::new(); let mut timing = HashMap::new();

View File

@ -10,6 +10,10 @@
// Should be used by F+F and non Naive F+R // Should be used by F+F and non Naive F+R
//use crate::naive::NaiveTimingChannelHandle; //use crate::naive::NaiveTimingChannelHandle;
use cache_side_channel::table_side_channel::{
MultipleTableCacheSideChannel, SingleTableCacheSideChannel, TableAttackResult,
TableCacheSideChannel,
};
use cache_side_channel::SideChannelError::AddressNotReady; use cache_side_channel::SideChannelError::AddressNotReady;
use cache_side_channel::{ use cache_side_channel::{
CacheStatus, ChannelFatalError, ChannelHandle, CoreSpec, MultipleAddrCacheSideChannel, CacheStatus, ChannelFatalError, ChannelHandle, CoreSpec, MultipleAddrCacheSideChannel,
@ -550,6 +554,33 @@ impl<T: TimingChannelPrimitives> MultipleAddrCacheSideChannel for TopologyAwareT
} }
} }
impl<T: TimingChannelPrimitives> SingleAddrCacheSideChannel for TopologyAwareTimingChannel<T> {
type Handle = TopologyAwareTimingChannelHandle;
unsafe fn test_single(
&mut self,
handle: &mut Self::Handle,
reset: bool,
) -> Result<CacheStatus, SideChannelError> {
unsafe { self.test_one_impl(handle, reset) }
}
unsafe fn prepare_single(&mut self, handle: &mut Self::Handle) -> Result<(), SideChannelError> {
unsafe { self.prepare_one_impl(handle) }
}
fn victim_single(&mut self, operation: &dyn Fn()) {
self.victim(operation)
}
unsafe fn calibrate_single(
&mut self,
addresses: impl IntoIterator<Item = *const u8> + Clone,
) -> Result<Vec<Self::Handle>, ChannelFatalError> {
unsafe { self.calibrate(addresses) }
}
}
impl<T: TimingChannelPrimitives> CovertChannel for TopologyAwareTimingChannel<T> { impl<T: TimingChannelPrimitives> CovertChannel for TopologyAwareTimingChannel<T> {
type CovertChannelHandle = CovertChannelHandle<TopologyAwareTimingChannel<T>>; type CovertChannelHandle = CovertChannelHandle<TopologyAwareTimingChannel<T>>;
const BIT_PER_PAGE: usize = 1; const BIT_PER_PAGE: usize = 1;
@ -656,19 +687,42 @@ impl<T: TimingChannelPrimitives> CovertChannel for TopologyAwareTimingChannel<T>
} }
} }
impl<T: TimingChannelPrimitives> TableCacheSideChannel<TopologyAwareTimingChannelHandle>
for TopologyAwareTimingChannel<T>
{
unsafe fn tcalibrate(
&mut self,
addresses: impl IntoIterator<Item = *const u8> + Clone,
) -> Result<Vec<TopologyAwareTimingChannelHandle>, ChannelFatalError> {
unsafe { self.tcalibrate_multi(addresses) }
}
unsafe fn attack<'a, 'b, 'c, 'd>(
&'a mut self,
addresses: &'b mut Vec<&'c mut TopologyAwareTimingChannelHandle>,
victim: &'d dyn Fn(),
num_iteration: u32,
) -> Result<Vec<TableAttackResult>, ChannelFatalError>
where
TopologyAwareTimingChannelHandle: 'c,
{
unsafe { self.attack_multi(addresses, victim, num_iteration) }
}
}
// Extra helper for single address per page variants. // Extra helper for single address per page variants.
#[derive(Debug)] #[derive(Debug)]
pub struct SingleChannel<T: MultipleAddrCacheSideChannel> { pub struct SingleChannel<T: SingleAddrCacheSideChannel> {
inner: T, inner: T,
} }
impl<T: MultipleAddrCacheSideChannel> SingleChannel<T> { impl<T: SingleAddrCacheSideChannel> SingleChannel<T> {
pub fn new(inner: T) -> Self { pub fn new(inner: T) -> Self {
Self { inner } Self { inner }
} }
} }
impl<T: MultipleAddrCacheSideChannel> CoreSpec for SingleChannel<T> { impl<T: SingleAddrCacheSideChannel> CoreSpec for SingleChannel<T> {
fn main_core(&self) -> CpuSet { fn main_core(&self) -> CpuSet {
self.inner.main_core() self.inner.main_core()
} }
@ -678,7 +732,7 @@ impl<T: MultipleAddrCacheSideChannel> CoreSpec for SingleChannel<T> {
} }
} }
impl<T: MultipleAddrCacheSideChannel> SingleAddrCacheSideChannel for SingleChannel<T> { impl<T: SingleAddrCacheSideChannel> SingleAddrCacheSideChannel for SingleChannel<T> {
type Handle = T::Handle; type Handle = T::Handle;
unsafe fn test_single( unsafe fn test_single(
@ -705,6 +759,31 @@ impl<T: MultipleAddrCacheSideChannel> SingleAddrCacheSideChannel for SingleChann
} }
} }
impl<T: SingleAddrCacheSideChannel>
TableCacheSideChannel<<SingleChannel<T> as SingleAddrCacheSideChannel>::Handle>
for SingleChannel<T>
{
unsafe fn tcalibrate(
&mut self,
addresses: impl IntoIterator<Item = *const u8> + Clone,
) -> Result<Vec<<SingleChannel<T> as SingleAddrCacheSideChannel>::Handle>, ChannelFatalError>
{
unsafe { self.inner.tcalibrate_single(addresses) }
}
unsafe fn attack<'a, 'b, 'c, 'd>(
&'a mut self,
addresses: &'b mut Vec<&'c mut <SingleChannel<T> as SingleAddrCacheSideChannel>::Handle>,
victim: &'d dyn Fn(),
num_iteration: u32,
) -> Result<Vec<TableAttackResult>, ChannelFatalError>
where
<SingleChannel<T> as SingleAddrCacheSideChannel>::Handle: 'c,
{
unsafe { self.inner.attack_single(addresses, victim, num_iteration) }
}
}
/* /*
impl<T: MultipleAddrCacheSideChannel + Sync + Send> CovertChannel for SingleChannel<T> { impl<T: MultipleAddrCacheSideChannel + Sync + Send> CovertChannel for SingleChannel<T> {
type Handle = CovertChannelHandle<T>; type Handle = CovertChannelHandle<T>;

View File

@ -1,4 +1,7 @@
use crate::TimingChannelPrimitives; use crate::TimingChannelPrimitives;
use cache_side_channel::table_side_channel::{
SingleTableCacheSideChannel, TableAttackResult, TableCacheSideChannel,
};
use cache_side_channel::{ use cache_side_channel::{
CacheStatus, ChannelFatalError, ChannelHandle, CoreSpec, MultipleAddrCacheSideChannel, CacheStatus, ChannelFatalError, ChannelHandle, CoreSpec, MultipleAddrCacheSideChannel,
SideChannelError, SingleAddrCacheSideChannel, SideChannelError, SingleAddrCacheSideChannel,
@ -65,7 +68,7 @@ impl<T: TimingChannelPrimitives> NaiveTimingChannel<T> {
//} //}
} }
unsafe fn test_impl( unsafe fn test_one_impl(
&self, &self,
handle: &mut NaiveTimingChannelHandle, handle: &mut NaiveTimingChannelHandle,
//limit: u32, //limit: u32,
@ -83,6 +86,39 @@ impl<T: TimingChannelPrimitives> NaiveTimingChannel<T> {
} }
} }
unsafe fn test_impl(
&self,
handles: &mut Vec<&mut NaiveTimingChannelHandle>,
limit: u32,
reset: bool,
) -> Result<Vec<(*const u8, CacheStatus)>, SideChannelError> {
let mut result = Vec::new();
let mut tmp = Vec::new();
let mut i = 0;
for addr in handles {
let r = unsafe { self.test_one_impl(addr, false) };
tmp.push((addr.to_const_u8_pointer(), r));
i += 1;
if i == limit {
break;
}
}
for (addr, r) in tmp {
match r {
Ok(status) => {
result.push((addr, status));
}
Err(e) => {
return Err(e);
}
}
if T::NEED_RESET && reset {
unsafe { flush(addr) };
}
}
Ok(result)
}
// The former invariant of one handle per page has been removed // The former invariant of one handle per page has been removed
// Now tolerates as many handles per cache line as wanted // Now tolerates as many handles per cache line as wanted
// should the invariant be fixed into one handle per cache line ? // should the invariant be fixed into one handle per cache line ?
@ -99,6 +135,36 @@ impl<T: TimingChannelPrimitives> NaiveTimingChannel<T> {
Ok(NaiveTimingChannelHandle { vpn, addr }) Ok(NaiveTimingChannelHandle { vpn, addr })
//} //}
} }
unsafe fn prepare_one_impl(
&mut self,
handle: &mut NaiveTimingChannelHandle,
) -> Result<(), SideChannelError> {
unsafe { flush(handle.addr) };
Ok(())
}
unsafe fn prepare_impl(
&mut self,
addresses: &mut Vec<&mut NaiveTimingChannelHandle>,
limit: u32,
) -> Result<(), SideChannelError> {
// Iterate on addresse prparig them, error early exit
let mut i = 0;
for handle in addresses {
match unsafe { self.prepare_one_impl(handle) } {
Ok(_) => {}
Err(e) => {
return Err(e);
}
}
i += 1;
if i == limit {
break;
}
}
Ok(())
}
} }
impl<T: TimingChannelPrimitives> CoreSpec for NaiveTimingChannel<T> { impl<T: TimingChannelPrimitives> CoreSpec for NaiveTimingChannel<T> {
@ -130,7 +196,7 @@ impl<T: TimingChannelPrimitives + Send + Sync> CovertChannel for NaiveTimingChan
} }
unsafe fn receive(&self, handle: &mut Self::CovertChannelHandle) -> Vec<bool> { unsafe fn receive(&self, handle: &mut Self::CovertChannelHandle) -> Vec<bool> {
let r = unsafe { self.test_impl(handle, false) }; let r = unsafe { self.test_one_impl(handle, false) };
match r { match r {
Err(e) => panic!(), Err(e) => panic!(),
Ok(status) => match status { Ok(status) => match status {
@ -153,12 +219,11 @@ impl<T: TimingChannelPrimitives> SingleAddrCacheSideChannel for NaiveTimingChann
handle: &mut Self::Handle, handle: &mut Self::Handle,
reset: bool, reset: bool,
) -> Result<CacheStatus, SideChannelError> { ) -> Result<CacheStatus, SideChannelError> {
unsafe { self.test_impl(handle, reset) } unsafe { self.test_one_impl(handle, reset) }
} }
unsafe fn prepare_single(&mut self, handle: &mut Self::Handle) -> Result<(), SideChannelError> { unsafe fn prepare_single(&mut self, handle: &mut Self::Handle) -> Result<(), SideChannelError> {
unsafe { flush(handle.addr) }; unsafe { self.prepare_one_impl(handle) }
Ok(())
} }
fn victim_single(&mut self, operation: &dyn Fn()) { fn victim_single(&mut self, operation: &dyn Fn()) {
@ -184,10 +249,10 @@ impl<T: TimingChannelPrimitives> SingleAddrCacheSideChannel for NaiveTimingChann
Ok(result) Ok(result)
} }
} }
/*
impl<T: TimingChannelPrimitives> MultipleAddrCacheSideChannel for NaiveTimingChannel<T> { impl<T: TimingChannelPrimitives> MultipleAddrCacheSideChannel for NaiveTimingChannel<T> {
type Handle = NaiveTimingChannelHandle; type Handle = NaiveTimingChannelHandle;
const MAX_ADDR: u32 = 0; const MAX_ADDR: u32 = 1;
unsafe fn test<'a>( unsafe fn test<'a>(
&mut self, &mut self,
@ -229,7 +294,29 @@ impl<T: TimingChannelPrimitives> MultipleAddrCacheSideChannel for NaiveTimingCha
Ok(result) Ok(result)
} }
} }
*/
impl<T: TimingChannelPrimitives> TableCacheSideChannel<NaiveTimingChannelHandle>
for NaiveTimingChannel<T>
{
unsafe fn tcalibrate(
&mut self,
addresses: impl IntoIterator<Item = *const u8> + Clone,
) -> Result<Vec<NaiveTimingChannelHandle>, ChannelFatalError> {
unsafe { self.tcalibrate_single(addresses) }
}
unsafe fn attack<'a, 'b, 'c, 'd>(
&'a mut self,
addresses: &'b mut Vec<&'c mut NaiveTimingChannelHandle>,
victim: &'d dyn Fn(),
num_iteration: u32,
) -> Result<Vec<TableAttackResult>, ChannelFatalError>
where
NaiveTimingChannelHandle: 'c,
{
unsafe { self.attack_single(addresses, victim, num_iteration) }
}
}
// Include a helper code to get global threshold model ? // Include a helper code to get global threshold model ?
// TODO // TODO

View File

@ -106,6 +106,7 @@ pub trait MultipleAddrCacheSideChannel: CoreSpec + Debug {
) -> Result<Vec<Self::Handle>, ChannelFatalError>; ) -> Result<Vec<Self::Handle>, ChannelFatalError>;
} }
/*
impl<T: MultipleAddrCacheSideChannel> SingleAddrCacheSideChannel for T { impl<T: MultipleAddrCacheSideChannel> SingleAddrCacheSideChannel for T {
type Handle = <Self as MultipleAddrCacheSideChannel>::Handle; type Handle = <Self as MultipleAddrCacheSideChannel>::Handle;
@ -134,6 +135,7 @@ impl<T: MultipleAddrCacheSideChannel> SingleAddrCacheSideChannel for T {
unsafe { self.calibrate(addresses) } unsafe { self.calibrate(addresses) }
} }
} }
*/
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {

View File

@ -26,7 +26,7 @@ pub trait TableCacheSideChannel<Handle: ChannelHandle>: CoreSpec + Debug {
/// # Safety /// # Safety
/// ///
/// addresses must contain only valid pointers to read. /// addresses must contain only valid pointers to read.
unsafe fn calibrate( unsafe fn tcalibrate(
&mut self, &mut self,
addresses: impl IntoIterator<Item = *const u8> + Clone, addresses: impl IntoIterator<Item = *const u8> + Clone,
) -> Result<Vec<Handle>, ChannelFatalError>; ) -> Result<Vec<Handle>, ChannelFatalError>;
@ -43,8 +43,51 @@ pub trait TableCacheSideChannel<Handle: ChannelHandle>: CoreSpec + Debug {
Handle: 'c; Handle: 'c;
} }
impl<T: SingleAddrCacheSideChannel> TableCacheSideChannel<T::Handle> for T { pub trait SingleTableCacheSideChannel<Handle: ChannelHandle>: CoreSpec + Debug {
default unsafe fn calibrate( //type ChannelFatalError: Debug;
/// # Safety
///
/// addresses must contain only valid pointers to read.
unsafe fn tcalibrate_single(
&mut self,
addresses: impl IntoIterator<Item = *const u8> + Clone,
) -> Result<Vec<Handle>, ChannelFatalError>;
/// # Safety
///
/// addresses must contain only valid pointers to read.
unsafe fn attack_single<'a, 'b, 'c, 'd>(
&'a mut self,
addresses: &'b mut Vec<&'c mut Handle>,
victim: &'d dyn Fn(),
num_iteration: u32,
) -> Result<Vec<TableAttackResult>, ChannelFatalError>
where
Handle: 'c;
}
pub trait MultipleTableCacheSideChannel<Handle: ChannelHandle>: CoreSpec + Debug {
//type ChannelFatalError: Debug;
/// # Safety
///
/// addresses must contain only valid pointers to read.
unsafe fn tcalibrate_multi(
&mut self,
addresses: impl IntoIterator<Item = *const u8> + Clone,
) -> Result<Vec<Handle>, ChannelFatalError>;
/// # Safety
///
/// addresses must contain only valid pointers to read.
unsafe fn attack_multi<'a, 'b, 'c, 'd>(
&'a mut self,
addresses: &'b mut Vec<&'c mut Handle>,
victim: &'d dyn Fn(),
num_iteration: u32,
) -> Result<Vec<TableAttackResult>, ChannelFatalError>
where
Handle: 'c;
}
impl<T: SingleAddrCacheSideChannel> SingleTableCacheSideChannel<T::Handle> for T {
default unsafe fn tcalibrate_single(
&mut self, &mut self,
addresses: impl IntoIterator<Item = *const u8> + Clone, addresses: impl IntoIterator<Item = *const u8> + Clone,
) -> Result<Vec<T::Handle>, ChannelFatalError> { ) -> Result<Vec<T::Handle>, ChannelFatalError> {
@ -52,7 +95,7 @@ impl<T: SingleAddrCacheSideChannel> TableCacheSideChannel<T::Handle> for T {
} }
//type ChannelFatalError = T::SingleChannelFatalError; //type ChannelFatalError = T::SingleChannelFatalError;
default unsafe fn attack<'a, 'b, 'c, 'd>( default unsafe fn attack_single<'a, 'b, 'c, 'd>(
&'a mut self, &'a mut self,
addresses: &'b mut Vec<&'c mut T::Handle>, addresses: &'b mut Vec<&'c mut T::Handle>,
victim: &'d dyn Fn(), victim: &'d dyn Fn(),
@ -122,8 +165,8 @@ impl<T: SingleAddrCacheSideChannel> TableCacheSideChannel<T::Handle> for T {
// TODO limit number of simultaneous tested address + randomise order ? // TODO limit number of simultaneous tested address + randomise order ?
impl<T: MultipleAddrCacheSideChannel> TableCacheSideChannel<T::Handle> for T { impl<T: MultipleAddrCacheSideChannel> MultipleTableCacheSideChannel<T::Handle> for T {
unsafe fn calibrate( unsafe fn tcalibrate_multi(
&mut self, &mut self,
addresses: impl IntoIterator<Item = *const u8> + Clone, addresses: impl IntoIterator<Item = *const u8> + Clone,
) -> Result<Vec<T::Handle>, ChannelFatalError> { ) -> Result<Vec<T::Handle>, ChannelFatalError> {
@ -134,7 +177,7 @@ impl<T: MultipleAddrCacheSideChannel> TableCacheSideChannel<T::Handle> for T {
/// # Safety /// # Safety
/// ///
/// addresses must contain only valid pointers to read. /// addresses must contain only valid pointers to read.
unsafe fn attack<'a, 'b, 'c, 'd>( unsafe fn attack_multi<'a, 'b, 'c, 'd>(
&'a mut self, &'a mut self,
mut addresses: &'b mut Vec<&'c mut T::Handle>, mut addresses: &'b mut Vec<&'c mut T::Handle>,
victim: &'d dyn Fn(), victim: &'d dyn Fn(),