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());
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() {
let mut timing = HashMap::new();

View File

@ -10,6 +10,10 @@
// Should be used by F+F and non Naive F+R
//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::{
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> {
type CovertChannelHandle = CovertChannelHandle<TopologyAwareTimingChannel<T>>;
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.
#[derive(Debug)]
pub struct SingleChannel<T: MultipleAddrCacheSideChannel> {
pub struct SingleChannel<T: SingleAddrCacheSideChannel> {
inner: T,
}
impl<T: MultipleAddrCacheSideChannel> SingleChannel<T> {
impl<T: SingleAddrCacheSideChannel> SingleChannel<T> {
pub fn new(inner: T) -> Self {
Self { inner }
}
}
impl<T: MultipleAddrCacheSideChannel> CoreSpec for SingleChannel<T> {
impl<T: SingleAddrCacheSideChannel> CoreSpec for SingleChannel<T> {
fn main_core(&self) -> CpuSet {
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;
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> {
type Handle = CovertChannelHandle<T>;

View File

@ -1,4 +1,7 @@
use crate::TimingChannelPrimitives;
use cache_side_channel::table_side_channel::{
SingleTableCacheSideChannel, TableAttackResult, TableCacheSideChannel,
};
use cache_side_channel::{
CacheStatus, ChannelFatalError, ChannelHandle, CoreSpec, MultipleAddrCacheSideChannel,
SideChannelError, SingleAddrCacheSideChannel,
@ -65,7 +68,7 @@ impl<T: TimingChannelPrimitives> NaiveTimingChannel<T> {
//}
}
unsafe fn test_impl(
unsafe fn test_one_impl(
&self,
handle: &mut NaiveTimingChannelHandle,
//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
// Now tolerates as many handles per cache line as wanted
// should the invariant be fixed into one handle per cache line ?
@ -99,6 +135,36 @@ impl<T: TimingChannelPrimitives> NaiveTimingChannel<T> {
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> {
@ -130,7 +196,7 @@ impl<T: TimingChannelPrimitives + Send + Sync> CovertChannel for NaiveTimingChan
}
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 {
Err(e) => panic!(),
Ok(status) => match status {
@ -153,12 +219,11 @@ impl<T: TimingChannelPrimitives> SingleAddrCacheSideChannel for NaiveTimingChann
handle: &mut Self::Handle,
reset: bool,
) -> 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 { flush(handle.addr) };
Ok(())
unsafe { self.prepare_one_impl(handle) }
}
fn victim_single(&mut self, operation: &dyn Fn()) {
@ -184,10 +249,10 @@ impl<T: TimingChannelPrimitives> SingleAddrCacheSideChannel for NaiveTimingChann
Ok(result)
}
}
/*
impl<T: TimingChannelPrimitives> MultipleAddrCacheSideChannel for NaiveTimingChannel<T> {
type Handle = NaiveTimingChannelHandle;
const MAX_ADDR: u32 = 0;
const MAX_ADDR: u32 = 1;
unsafe fn test<'a>(
&mut self,
@ -229,7 +294,29 @@ impl<T: TimingChannelPrimitives> MultipleAddrCacheSideChannel for NaiveTimingCha
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 ?
// TODO

View File

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

View File

@ -26,7 +26,7 @@ pub trait TableCacheSideChannel<Handle: ChannelHandle>: CoreSpec + Debug {
/// # Safety
///
/// addresses must contain only valid pointers to read.
unsafe fn calibrate(
unsafe fn tcalibrate(
&mut self,
addresses: impl IntoIterator<Item = *const u8> + Clone,
) -> Result<Vec<Handle>, ChannelFatalError>;
@ -43,8 +43,51 @@ pub trait TableCacheSideChannel<Handle: ChannelHandle>: CoreSpec + Debug {
Handle: 'c;
}
impl<T: SingleAddrCacheSideChannel> TableCacheSideChannel<T::Handle> for T {
default unsafe fn calibrate(
pub trait SingleTableCacheSideChannel<Handle: ChannelHandle>: CoreSpec + Debug {
//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,
addresses: impl IntoIterator<Item = *const u8> + Clone,
) -> Result<Vec<T::Handle>, ChannelFatalError> {
@ -52,7 +95,7 @@ impl<T: SingleAddrCacheSideChannel> TableCacheSideChannel<T::Handle> for T {
}
//type ChannelFatalError = T::SingleChannelFatalError;
default unsafe fn attack<'a, 'b, 'c, 'd>(
default unsafe fn attack_single<'a, 'b, 'c, 'd>(
&'a mut self,
addresses: &'b mut Vec<&'c mut T::Handle>,
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 ?
impl<T: MultipleAddrCacheSideChannel> TableCacheSideChannel<T::Handle> for T {
unsafe fn calibrate(
impl<T: MultipleAddrCacheSideChannel> MultipleTableCacheSideChannel<T::Handle> for T {
unsafe fn tcalibrate_multi(
&mut self,
addresses: impl IntoIterator<Item = *const u8> + Clone,
) -> Result<Vec<T::Handle>, ChannelFatalError> {
@ -134,7 +177,7 @@ impl<T: MultipleAddrCacheSideChannel> TableCacheSideChannel<T::Handle> for T {
/// # Safety
///
/// 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,
mut addresses: &'b mut Vec<&'c mut T::Handle>,
victim: &'d dyn Fn(),