Skip to content

Commit

Permalink
Merge pull request #350 from iotaledger/security/enhance-memory-alloc…
Browse files Browse the repository at this point in the history
…ation

[Security] Enhance Memory Allocation
  • Loading branch information
felsweg-iota authored Jul 13, 2022
2 parents 6473ace + da14dfd commit e9c3ebc
Show file tree
Hide file tree
Showing 19 changed files with 1,182 additions and 200 deletions.
10 changes: 7 additions & 3 deletions engine/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,10 @@ proptest = "1.0.0"
criterion = "0.3.3"
json = "0.12"

[dev-dependencies.stronghold-utils]
path = "../utils"
version = "0.4.1"
[[bench]]
name = "engine_bench"
harness = false

[dev-dependencies.stronghold-utils]
path = "../utils"
version = "0.4.1"
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,6 @@ criterion_group!(
bench_store_compress,
bench_store_compression,
bench_store_decompress,
bench_vault_write
bench_vault_write,
);
criterion_main!(benches);
17 changes: 16 additions & 1 deletion engine/runtime/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@ categories = [ "security" ]
name = "runtime"

[dependencies]
libc = { version = "0.2" }
log = { version = "0.4.17" }
zeroize = { version = "1.4.3" }
libsodium-sys = { version = "0.2" }
serde = { version = "1.0", features = [ "derive" ] }
Expand All @@ -24,5 +26,18 @@ dirs = { version = "4.0.0" }
thiserror = { version = "1.0" }
iota-crypto = { version = "0.12.1", features = [ "blake2b" ] }

[target.'cfg(windows)'.dependencies]
windows = { version = "0.36.0", features = ["Win32_System_Memory", "Win32_System_SystemInformation", "Win32_System_Diagnostics_Debug", "Win32_Foundation", "Win32_Security"] }

[target.'cfg(any(target_os = "linux", target_os = "macos"))'.dependencies]
nix = { version = "0.24.1" }

[dev-dependencies]
serde_json = { version = "1.0" }
serde_json = { version = "1.0" }
env_logger = { version = "0.9" }
dhat = { version = "0.3" }
criterion = "0.3.3"

[[bench]]
name = "runtime_bench"
harness = false
5 changes: 2 additions & 3 deletions engine/runtime/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ This crate provides multiple ways to store data securely whether in ram, disk or
All these types of memories implement the `LockedMemory` trait which enables one to allocate or unlock the data stored.
A `Buffer` type which implements basic security measures is also provided to temporarily store data for any computation.


## `Buffer`
Memory which contains some "minimal" security measures such as:
- Guard areas
Expand Down Expand Up @@ -78,8 +77,8 @@ Hence data security depends on the strength of the encryption scheme and the 'ob
- [x] `NonContiguousMemory`
- [ ] Tests
- [x] Functional correctness
- [ ] Security
- [x] Security
- [x] zeroize
- [ ] access to the locked memory
- [ ] Benchmarks
- [x] Benchmarks
- [ ] no-std
92 changes: 92 additions & 0 deletions engine/runtime/benches/runtime_bench.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
// Copyright 2020-2021 IOTA Stiftung
// SPDX-License-Identifier: Apache-2.0

use criterion::{criterion_group, criterion_main, Criterion};
use runtime::{
locked_memory::LockedMemory,
memories::{
frag::FragStrategy,
noncontiguous_memory::{
NCConfig::{self, *},
*,
},
},
utils::random_vec,
};

#[allow(dead_code)]
struct TestStruct {
id: usize,
name: String,
}

impl Default for TestStruct {
fn default() -> Self {
Self {
id: 0xFFFF_FFFF_FFFF_FFFF,
name: "Some TestingStruct".to_owned(),
}
}
}

fn bench_ncm_full_ram(c: &mut Criterion) {
bench_ncm(c, FullRam);
}

fn bench_ncm_full_file(c: &mut Criterion) {
bench_ncm(c, FullFile);
}

fn bench_ncm_ram_file(c: &mut Criterion) {
bench_ncm(c, RamAndFile);
}

fn bench_ncm_frag_direct(c: &mut Criterion) {
bench_ncm(c, FragAllocation(FragStrategy::Direct));
}

fn bench_ncm_frag_map(c: &mut Criterion) {
bench_ncm(c, FragAllocation(FragStrategy::Map));
}

fn bench_ncm_frag_hybrid(c: &mut Criterion) {
bench_ncm(c, FragAllocation(FragStrategy::Hybrid));
}

fn bench_ncm(c: &mut Criterion, config: NCConfig) {
let bench_name = match config {
FullRam => "NCM full ram",
FullFile => "NCM full file",
RamAndFile => "NCM ram and file",
FragAllocation(frag) => match frag {
FragStrategy::Direct => "NCM fragment direct",
FragStrategy::Map => "NCM fragment map",
FragStrategy::Hybrid => "NCM fragment hybrid",
},
};

let data = random_vec(NC_DATA_SIZE);

c.bench_function(bench_name, |b| {
b.iter(|| {
// Allocate
let ncm = NonContiguousMemory::alloc(&data, NC_DATA_SIZE, config.clone()).expect("error while allocating");

// Unlock non-contiguous memory few times to refresh the shards
for _ in 0..10 {
let _ = ncm.unlock().expect("error while unlocking");
}
});
});
}

criterion_group!(
benches,
bench_ncm_full_ram,
bench_ncm_full_file,
bench_ncm_ram_file,
bench_ncm_frag_direct,
bench_ncm_frag_map,
bench_ncm_frag_hybrid,
);
criterion_main!(benches);
7 changes: 7 additions & 0 deletions engine/runtime/src/boxed.rs
Original file line number Diff line number Diff line change
Expand Up @@ -205,6 +205,13 @@ impl<T: Bytes> Boxed<T> {
fn is_locked(&self) -> bool {
self.prot.get() == Prot::NoAccess
}

#[cfg(test)]
#[allow(dead_code)]
/// Returns the address of the pointer to the data
pub fn get_ptr_address(&self) -> usize {
self.ptr.as_ptr() as *const _ as usize
}
}

impl<T: Bytes + Randomized> Boxed<T> {
Expand Down
12 changes: 12 additions & 0 deletions engine/runtime/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,9 @@ pub enum MemoryError {
#[error("Illegal non-contiguous size")]
NCSizeNotAllowed,

#[error("Error while refreshing non-contiguous memory")]
NCRefreshError,

#[error("Lock unavailable")]
LockNotAvailable,

Expand All @@ -36,6 +39,15 @@ pub enum MemoryError {

#[error("Illegal zero-sized value provided")]
ZeroSizedNotAllowed,

#[error("Failed to allocate memory ({0})")]
Allocation(String),

#[error("Intended operation failed: ({0})")]
Operation(String),

#[error("Illegal tentative of using zeroized memory")]
IllegalZeroizedUsage,
}

/// A simple trait to force the types to call `zeroize()` when dropping
Expand Down
11 changes: 9 additions & 2 deletions engine/runtime/src/memories/buffer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ use serde::{
/// This shall always be short lived
#[derive(Clone, Eq)]
pub struct Buffer<T: Bytes> {
boxed: Boxed<T>, // the boxed type of current GuardedVec
boxed: Boxed<T>, // the boxed type of current GuardedVec,
}

pub struct Ref<'a, T: Bytes> {
Expand Down Expand Up @@ -63,6 +63,13 @@ impl<T: Bytes> Buffer<T> {
pub fn borrow_mut(&mut self) -> RefMut<'_, T> {
RefMut::new(&mut self.boxed)
}

#[cfg(test)]
#[allow(dead_code)]
/// Returns the address of the pointer to the data
pub fn get_ptr_address(&self) -> usize {
self.boxed.get_ptr_address()
}
}

impl<T: Bytes + Randomized> Buffer<T> {
Expand All @@ -82,7 +89,7 @@ impl<T: Bytes> Zeroize for Buffer<T> {

impl<T: Bytes> Drop for Buffer<T> {
fn drop(&mut self) {
self.boxed.zeroize()
self.boxed.zeroize();
}
}

Expand Down
Loading

0 comments on commit e9c3ebc

Please sign in to comment.