mirror of
https://github.com/rosenpass/rosenpass.git
synced 2025-12-18 21:34:37 +03:00
chore: Move Public and debug_crypto_array into secret-memory crate
This commit is contained in:
committed by
Karolin Varner
parent
36089fd37f
commit
7bda010a9b
11
Cargo.lock
generated
11
Cargo.lock
generated
@@ -1073,6 +1073,7 @@ dependencies = [
|
|||||||
"paste",
|
"paste",
|
||||||
"rosenpass-ciphers",
|
"rosenpass-ciphers",
|
||||||
"rosenpass-constant-time",
|
"rosenpass-constant-time",
|
||||||
|
"rosenpass-secret-memory",
|
||||||
"rosenpass-sodium",
|
"rosenpass-sodium",
|
||||||
"rosenpass-to",
|
"rosenpass-to",
|
||||||
"rosenpass-util",
|
"rosenpass-util",
|
||||||
@@ -1116,6 +1117,16 @@ dependencies = [
|
|||||||
"stacker",
|
"stacker",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "rosenpass-secret-memory"
|
||||||
|
version = "0.1.0"
|
||||||
|
dependencies = [
|
||||||
|
"anyhow",
|
||||||
|
"rosenpass-sodium",
|
||||||
|
"rosenpass-to",
|
||||||
|
"rosenpass-util",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "rosenpass-sodium"
|
name = "rosenpass-sodium"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ members = [
|
|||||||
"sodium",
|
"sodium",
|
||||||
"to",
|
"to",
|
||||||
"fuzz",
|
"fuzz",
|
||||||
|
"secret-memory",
|
||||||
]
|
]
|
||||||
|
|
||||||
default-members = [
|
default-members = [
|
||||||
@@ -26,6 +27,7 @@ rosenpass-constant-time = { path = "constant-time" }
|
|||||||
rosenpass-sodium = { path = "sodium" }
|
rosenpass-sodium = { path = "sodium" }
|
||||||
rosenpass-ciphers = { path = "ciphers" }
|
rosenpass-ciphers = { path = "ciphers" }
|
||||||
rosenpass-to = { path = "to" }
|
rosenpass-to = { path = "to" }
|
||||||
|
rosenpass-secret-memory = { path = "secret-memory" }
|
||||||
criterion = "0.4.0"
|
criterion = "0.4.0"
|
||||||
test_bin = "0.4.0"
|
test_bin = "0.4.0"
|
||||||
libfuzzer-sys = "0.4"
|
libfuzzer-sys = "0.4"
|
||||||
@@ -47,4 +49,4 @@ arbitrary = { version = "1.3.2", features = ["derive"] }
|
|||||||
anyhow = { version = "1.0.71", features = ["backtrace"] }
|
anyhow = { version = "1.0.71", features = ["backtrace"] }
|
||||||
mio = { version = "0.8.6", features = ["net", "os-poll"] }
|
mio = { version = "0.8.6", features = ["net", "os-poll"] }
|
||||||
libsodium-sys-stable= { version = "1.19.28", features = ["use-pkg-config"] }
|
libsodium-sys-stable= { version = "1.19.28", features = ["use-pkg-config"] }
|
||||||
oqs-sys = { version = "0.8", default-features = false, features = ['classic_mceliece', 'kyber'] }
|
oqs-sys = { version = "0.8", default-features = false, features = ['classic_mceliece', 'kyber'] }
|
||||||
|
|||||||
@@ -19,6 +19,7 @@ rosenpass-constant-time = { workspace = true }
|
|||||||
rosenpass-sodium = { workspace = true }
|
rosenpass-sodium = { workspace = true }
|
||||||
rosenpass-ciphers = { workspace = true }
|
rosenpass-ciphers = { workspace = true }
|
||||||
rosenpass-to = { workspace = true }
|
rosenpass-to = { workspace = true }
|
||||||
|
rosenpass-secret-memory = { workspace = true }
|
||||||
anyhow = { workspace = true }
|
anyhow = { workspace = true }
|
||||||
static_assertions = { workspace = true }
|
static_assertions = { workspace = true }
|
||||||
memoffset = { workspace = true }
|
memoffset = { workspace = true }
|
||||||
|
|||||||
@@ -1,11 +1,3 @@
|
|||||||
//! Types types for dealing with (secret-) values
|
|
||||||
//!
|
|
||||||
//! These types use type level coloring to make accidential leackage of secrets extra hard. Both [Secret] and [Public] own their data, but the memory backing
|
|
||||||
//! [Secret] is special:
|
|
||||||
//! - as it is heap allocated, we can actively zeroize the memory before freeing it.
|
|
||||||
//! - guard pages before and after each allocation trap accidential sequential reads that creep towards our secrets
|
|
||||||
//! - the memory is mlocked, e.g. it is never swapped
|
|
||||||
|
|
||||||
use anyhow::Context;
|
use anyhow::Context;
|
||||||
use lazy_static::lazy_static;
|
use lazy_static::lazy_static;
|
||||||
use libsodium_sys as libsodium;
|
use libsodium_sys as libsodium;
|
||||||
@@ -13,17 +5,10 @@ use rosenpass_util::{
|
|||||||
b64::b64_reader,
|
b64::b64_reader,
|
||||||
file::{fopen_r, LoadValue, LoadValueB64, ReadExactToEnd, StoreValue},
|
file::{fopen_r, LoadValue, LoadValueB64, ReadExactToEnd, StoreValue},
|
||||||
functional::mutating,
|
functional::mutating,
|
||||||
mem::cpy,
|
|
||||||
};
|
};
|
||||||
use std::result::Result;
|
use std::result::Result;
|
||||||
use std::{
|
use std::{
|
||||||
collections::HashMap,
|
collections::HashMap, convert::TryInto, fmt, os::raw::c_void, path::Path, ptr::null_mut,
|
||||||
convert::TryInto,
|
|
||||||
fmt,
|
|
||||||
ops::{Deref, DerefMut},
|
|
||||||
os::raw::c_void,
|
|
||||||
path::Path,
|
|
||||||
ptr::null_mut,
|
|
||||||
sync::Mutex,
|
sync::Mutex,
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -216,81 +201,6 @@ impl<const N: usize> fmt::Debug for Secret<N> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Contains information in the form of a byte array that may be known to the
|
|
||||||
/// public
|
|
||||||
// TODO: We should get rid of the Public type; just use a normal value
|
|
||||||
#[derive(Copy, Clone, Hash, PartialEq, Eq, PartialOrd, Ord)]
|
|
||||||
#[repr(transparent)]
|
|
||||||
pub struct Public<const N: usize> {
|
|
||||||
pub value: [u8; N],
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<const N: usize> Public<N> {
|
|
||||||
/// Create a new [Public] from a byte slice
|
|
||||||
pub fn from_slice(value: &[u8]) -> Self {
|
|
||||||
mutating(Self::zero(), |r| cpy(value, &mut r.value))
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Create a new [Public] from a byte array
|
|
||||||
pub fn new(value: [u8; N]) -> Self {
|
|
||||||
Self { value }
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Create a zero initialized [Public]
|
|
||||||
pub fn zero() -> Self {
|
|
||||||
Self { value: [0u8; N] }
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Create a random initialized [Public]
|
|
||||||
pub fn random() -> Self {
|
|
||||||
mutating(Self::zero(), |r| r.randomize())
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Randomize all bytes in an existing [Public]
|
|
||||||
pub fn randomize(&mut self) {
|
|
||||||
rosenpass_sodium::helpers::randombytes_buf(&mut self.value);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Writes the contents of an `&[u8]` as hexadecimal symbols to a [std::fmt::Formatter]
|
|
||||||
pub fn debug_crypto_array(v: &[u8], fmt: &mut fmt::Formatter) -> fmt::Result {
|
|
||||||
fmt.write_str("[{}]=")?;
|
|
||||||
if v.len() > 64 {
|
|
||||||
for byte in &v[..32] {
|
|
||||||
std::fmt::LowerHex::fmt(byte, fmt)?;
|
|
||||||
}
|
|
||||||
fmt.write_str("…")?;
|
|
||||||
for byte in &v[v.len() - 32..] {
|
|
||||||
std::fmt::LowerHex::fmt(byte, fmt)?;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
for byte in v {
|
|
||||||
std::fmt::LowerHex::fmt(byte, fmt)?;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<const N: usize> fmt::Debug for Public<N> {
|
|
||||||
fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
|
|
||||||
debug_crypto_array(&self.value, fmt)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<const N: usize> Deref for Public<N> {
|
|
||||||
type Target = [u8; N];
|
|
||||||
|
|
||||||
fn deref(&self) -> &[u8; N] {
|
|
||||||
&self.value
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<const N: usize> DerefMut for Public<N> {
|
|
||||||
fn deref_mut(&mut self) -> &mut [u8; N] {
|
|
||||||
&mut self.value
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod test {
|
mod test {
|
||||||
use super::*;
|
use super::*;
|
||||||
@@ -422,22 +332,3 @@ impl<const N: usize> StoreSecret for Secret<N> {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<const N: usize> LoadValue for Public<N> {
|
|
||||||
type Error = anyhow::Error;
|
|
||||||
|
|
||||||
fn load<P: AsRef<Path>>(path: P) -> anyhow::Result<Self> {
|
|
||||||
let mut v = Self::random();
|
|
||||||
fopen_r(path)?.read_exact_to_end(&mut *v)?;
|
|
||||||
Ok(v)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<const N: usize> StoreValue for Public<N> {
|
|
||||||
type Error = anyhow::Error;
|
|
||||||
|
|
||||||
fn store<P: AsRef<Path>>(&self, path: P) -> anyhow::Result<()> {
|
|
||||||
std::fs::write(path, **self)?;
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -76,6 +76,7 @@ use crate::{
|
|||||||
};
|
};
|
||||||
use anyhow::{bail, ensure, Context, Result};
|
use anyhow::{bail, ensure, Context, Result};
|
||||||
use rosenpass_ciphers::{aead, xaead, KEY_LEN};
|
use rosenpass_ciphers::{aead, xaead, KEY_LEN};
|
||||||
|
use rosenpass_secret_memory::Public;
|
||||||
use rosenpass_util::{cat, mem::cpy_min, ord::max_usize, time::Timebase};
|
use rosenpass_util::{cat, mem::cpy_min, ord::max_usize, time::Timebase};
|
||||||
use std::collections::hash_map::{
|
use std::collections::hash_map::{
|
||||||
Entry::{Occupied, Vacant},
|
Entry::{Occupied, Vacant},
|
||||||
|
|||||||
16
secret-memory/Cargo.toml
Normal file
16
secret-memory/Cargo.toml
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
[package]
|
||||||
|
name = "rosenpass-secret-memory"
|
||||||
|
version = "0.1.0"
|
||||||
|
authors = ["Karolin Varner <karo@cupdev.net>", "wucke13 <wucke13@gmail.com>"]
|
||||||
|
edition = "2021"
|
||||||
|
license = "MIT OR Apache-2.0"
|
||||||
|
description = "Rosenpass internal utilities for storing secrets in memory"
|
||||||
|
homepage = "https://rosenpass.eu/"
|
||||||
|
repository = "https://github.com/rosenpass/rosenpass"
|
||||||
|
readme = "readme.md"
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
anyhow = { workspace = true }
|
||||||
|
rosenpass-to = { workspace = true }
|
||||||
|
rosenpass-sodium = { workspace = true }
|
||||||
|
rosenpass-util = { workspace = true }
|
||||||
5
secret-memory/readme.md
Normal file
5
secret-memory/readme.md
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
# Rosenpass secure memory library
|
||||||
|
|
||||||
|
Rosenpass internal library providing utilities for securely storing secret data in memory.
|
||||||
|
|
||||||
|
This is an internal library; not guarantee is made about its API at this point in time.
|
||||||
20
secret-memory/src/debug.rs
Normal file
20
secret-memory/src/debug.rs
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
use std::fmt;
|
||||||
|
|
||||||
|
/// Writes the contents of an `&[u8]` as hexadecimal symbols to a [std::fmt::Formatter]
|
||||||
|
pub fn debug_crypto_array(v: &[u8], fmt: &mut fmt::Formatter) -> fmt::Result {
|
||||||
|
fmt.write_str("[{}]=")?;
|
||||||
|
if v.len() > 64 {
|
||||||
|
for byte in &v[..32] {
|
||||||
|
std::fmt::LowerHex::fmt(byte, fmt)?;
|
||||||
|
}
|
||||||
|
fmt.write_str("…")?;
|
||||||
|
for byte in &v[v.len() - 32..] {
|
||||||
|
std::fmt::LowerHex::fmt(byte, fmt)?;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
for byte in v {
|
||||||
|
std::fmt::LowerHex::fmt(byte, fmt)?;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
4
secret-memory/src/lib.rs
Normal file
4
secret-memory/src/lib.rs
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
mod public;
|
||||||
|
pub use crate::public::Public;
|
||||||
|
|
||||||
|
pub mod debug;
|
||||||
105
secret-memory/src/public.rs
Normal file
105
secret-memory/src/public.rs
Normal file
@@ -0,0 +1,105 @@
|
|||||||
|
use crate::debug::debug_crypto_array;
|
||||||
|
use rosenpass_to::{ops::copy_slice, To};
|
||||||
|
use rosenpass_util::file::{fopen_r, LoadValue, ReadExactToEnd, StoreValue};
|
||||||
|
use rosenpass_util::functional::mutating;
|
||||||
|
use std::borrow::{Borrow, BorrowMut};
|
||||||
|
use std::fmt;
|
||||||
|
use std::ops::{Deref, DerefMut};
|
||||||
|
use std::path::Path;
|
||||||
|
|
||||||
|
/// Contains information in the form of a byte array that may be known to the
|
||||||
|
/// public
|
||||||
|
// TODO: We should get rid of the Public type; just use a normal value
|
||||||
|
#[derive(Copy, Clone, Hash, PartialEq, Eq, PartialOrd, Ord)]
|
||||||
|
#[repr(transparent)]
|
||||||
|
pub struct Public<const N: usize> {
|
||||||
|
pub value: [u8; N],
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<const N: usize> Public<N> {
|
||||||
|
/// Create a new [Public] from a byte slice
|
||||||
|
pub fn from_slice(value: &[u8]) -> Self {
|
||||||
|
copy_slice(value).to_this(|| Self::zero())
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Create a new [Public] from a byte array
|
||||||
|
pub fn new(value: [u8; N]) -> Self {
|
||||||
|
Self { value }
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Create a zero initialized [Public]
|
||||||
|
pub fn zero() -> Self {
|
||||||
|
Self { value: [0u8; N] }
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Create a random initialized [Public]
|
||||||
|
pub fn random() -> Self {
|
||||||
|
mutating(Self::zero(), |r| r.randomize())
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Randomize all bytes in an existing [Public]
|
||||||
|
pub fn randomize(&mut self) {
|
||||||
|
rosenpass_sodium::helpers::randombytes_buf(&mut self.value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<const N: usize> fmt::Debug for Public<N> {
|
||||||
|
fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
|
||||||
|
debug_crypto_array(&self.value, fmt)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<const N: usize> Deref for Public<N> {
|
||||||
|
type Target = [u8; N];
|
||||||
|
|
||||||
|
fn deref(&self) -> &[u8; N] {
|
||||||
|
&self.value
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<const N: usize> DerefMut for Public<N> {
|
||||||
|
fn deref_mut(&mut self) -> &mut [u8; N] {
|
||||||
|
&mut self.value
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<const N: usize> Borrow<[u8; N]> for Public<N> {
|
||||||
|
fn borrow(&self) -> &[u8; N] {
|
||||||
|
&self.value
|
||||||
|
}
|
||||||
|
}
|
||||||
|
impl<const N: usize> BorrowMut<[u8; N]> for Public<N> {
|
||||||
|
fn borrow_mut(&mut self) -> &mut [u8; N] {
|
||||||
|
&mut self.value
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<const N: usize> Borrow<[u8]> for Public<N> {
|
||||||
|
fn borrow(&self) -> &[u8] {
|
||||||
|
&self.value
|
||||||
|
}
|
||||||
|
}
|
||||||
|
impl<const N: usize> BorrowMut<[u8]> for Public<N> {
|
||||||
|
fn borrow_mut(&mut self) -> &mut [u8] {
|
||||||
|
&mut self.value
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<const N: usize> LoadValue for Public<N> {
|
||||||
|
type Error = anyhow::Error;
|
||||||
|
|
||||||
|
fn load<P: AsRef<Path>>(path: P) -> anyhow::Result<Self> {
|
||||||
|
let mut v = Self::random();
|
||||||
|
fopen_r(path)?.read_exact_to_end(&mut *v)?;
|
||||||
|
Ok(v)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<const N: usize> StoreValue for Public<N> {
|
||||||
|
type Error = anyhow::Error;
|
||||||
|
|
||||||
|
fn store<P: AsRef<Path>>(&self, path: P) -> anyhow::Result<()> {
|
||||||
|
std::fs::write(path, **self)?;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user