-
Notifications
You must be signed in to change notification settings - Fork 37
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge branch 'main' into sm/sm-1237_2
- Loading branch information
Showing
26 changed files
with
593 additions
and
130 deletions.
There are no files selected for viewing
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
use criterion::{black_box, criterion_group, criterion_main, Criterion}; | ||
|
||
fn allocate_string(s: &str) -> String { | ||
s.to_owned() | ||
} | ||
|
||
pub fn criterion_benchmark(c: &mut Criterion) { | ||
c.bench_function("string abc", |b| { | ||
b.iter(|| allocate_string(black_box("abc"))) | ||
}); | ||
} | ||
|
||
criterion_group!(benches, criterion_benchmark); | ||
criterion_main!(benches); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
use bitwarden_crypto::ZeroizingAllocator; | ||
use criterion::{criterion_group, criterion_main}; | ||
use default_allocator::criterion_benchmark; | ||
|
||
#[global_allocator] | ||
static ALLOC: ZeroizingAllocator<std::alloc::System> = ZeroizingAllocator(std::alloc::System); | ||
|
||
mod default_allocator; | ||
|
||
criterion_group!(benches, criterion_benchmark); | ||
criterion_main!(benches); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,167 @@ | ||
use core::slice; | ||
use std::alloc::{GlobalAlloc, Layout}; | ||
|
||
use zeroize::Zeroize; | ||
|
||
/// Custom allocator that zeroizes memory before deallocating it | ||
/// | ||
/// This is highly recommended to be enabled when using the Bitwarden crates to avoid sensitive data | ||
/// persisting in memory after it has been deallocated. | ||
/// | ||
/// This allocator is a decorator around another allocator. | ||
/// | ||
/// # Example | ||
/// | ||
/// This example shows how to use the `ZeroizingAllocator` with the system allocator. | ||
/// | ||
/// ```rust,ignore | ||
/// #[global_allocator] | ||
/// static ALLOC: bitwarden_crypto::ZeroizingAllocator<std::alloc::System> = | ||
/// bitwarden_crypto::ZeroizingAllocator(std::alloc::System); | ||
/// ``` | ||
pub struct ZeroizingAllocator<Alloc: GlobalAlloc>(pub Alloc); | ||
|
||
unsafe impl<T: GlobalAlloc> GlobalAlloc for ZeroizingAllocator<T> { | ||
unsafe fn alloc(&self, layout: Layout) -> *mut u8 { | ||
self.0.alloc(layout) | ||
} | ||
|
||
unsafe fn dealloc(&self, ptr: *mut u8, layout: Layout) { | ||
slice::from_raw_parts_mut(ptr, layout.size()).zeroize(); | ||
|
||
self.0.dealloc(ptr, layout); | ||
} | ||
|
||
unsafe fn alloc_zeroed(&self, layout: Layout) -> *mut u8 { | ||
self.0.alloc_zeroed(layout) | ||
} | ||
} | ||
|
||
#[cfg(test)] | ||
mod tests { | ||
#[test] | ||
#[ignore = "It produces inconsistent results on some platforms"] | ||
fn string() { | ||
let s = String::from("hello"); | ||
|
||
let p1 = s.as_str().as_ptr(); | ||
let c1 = s.capacity(); | ||
|
||
assert_eq!( | ||
unsafe { std::slice::from_raw_parts(p1, c1) }, | ||
b"hello", | ||
"String is not at the expected memory location" | ||
); | ||
|
||
drop(s); | ||
|
||
assert_eq!( | ||
unsafe { std::slice::from_raw_parts(p1, c1) }, | ||
[0, 0, 0, 0, 0], | ||
"memory was not zeroized after dropping the string" | ||
); | ||
} | ||
|
||
#[test] | ||
#[ignore = "It produces inconsistent results on some platforms"] | ||
fn string_expand() { | ||
let mut s = String::from("hello"); | ||
|
||
let p1 = s.as_str().as_ptr(); | ||
let c1 = s.capacity(); | ||
|
||
assert_eq!(unsafe { std::slice::from_raw_parts(p1, c1) }, b"hello"); | ||
|
||
s.push_str(" world"); | ||
|
||
let p2 = s.as_str().as_ptr(); | ||
let c2 = s.capacity(); | ||
|
||
// We allocated a new string | ||
assert_ne!(p1, p2); | ||
assert_eq!( | ||
unsafe { std::slice::from_raw_parts(p1, c1) }, | ||
[0, 0, 0, 0, 0], | ||
"old string was not zeroized" | ||
); | ||
|
||
assert_eq!( | ||
unsafe { std::slice::from_raw_parts(p2, c2) }, | ||
b"hello world" | ||
); | ||
|
||
// Drop the expanded string | ||
drop(s); | ||
|
||
assert_eq!( | ||
unsafe { std::slice::from_raw_parts(p2, c2) }, | ||
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], | ||
"expanded string was not zeroized" | ||
); | ||
} | ||
|
||
#[test] | ||
#[ignore = "It produces inconsistent results on some platforms"] | ||
fn vec() { | ||
let v = vec![1, 2, 3, 4, 5]; | ||
|
||
let p1 = v.as_slice().as_ptr(); | ||
let c1 = v.capacity(); | ||
|
||
assert_eq!( | ||
unsafe { std::slice::from_raw_parts(p1, c1) }, | ||
[1, 2, 3, 4, 5], | ||
"vec is not at the expected memory location" | ||
); | ||
|
||
drop(v); | ||
|
||
assert_eq!( | ||
unsafe { std::slice::from_raw_parts(p1, c1) }, | ||
[0, 0, 0, 0, 0], | ||
"vec was not zeroized after dropping" | ||
); | ||
} | ||
|
||
#[test] | ||
#[ignore = "It produces inconsistent results on some platforms"] | ||
fn vec_expand() { | ||
let mut v = vec![1, 2, 3, 4, 5]; | ||
|
||
let p1 = v.as_slice().as_ptr(); | ||
let c1 = v.capacity(); | ||
|
||
assert_eq!( | ||
unsafe { std::slice::from_raw_parts(p1, c1) }, | ||
[1, 2, 3, 4, 5], | ||
"vec is not at the expected memory location" | ||
); | ||
|
||
v.extend_from_slice(&[6, 7, 8, 9, 10]); | ||
|
||
let p2 = v.as_slice().as_ptr(); | ||
let c2 = v.capacity(); | ||
|
||
// We allocated a new vector | ||
assert_ne!(p1, p2); | ||
assert_eq!( | ||
unsafe { std::slice::from_raw_parts(p1, c1) }, | ||
[0, 0, 0, 0, 0], | ||
"old vec was not zeroized" | ||
); | ||
|
||
assert_eq!( | ||
unsafe { std::slice::from_raw_parts(p2, c2) }, | ||
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10] | ||
); | ||
|
||
// Drop the expanded vector | ||
drop(v); | ||
|
||
assert_eq!( | ||
unsafe { std::slice::from_raw_parts(p2, c2) }, | ||
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0], | ||
"expanded vec was not zeroized" | ||
); | ||
} | ||
} |
Oops, something went wrong.