mirror of
https://github.com/rosenpass/rosenpass.git
synced 2026-02-28 06:23:08 -08:00
Move static KEM public key to new PublicBox struct
This commit is contained in:
committed by
kat watson
parent
bdad414c90
commit
a18658847c
@@ -6,7 +6,7 @@ use rosenpass_secret_memory::file::StoreSecret;
|
||||
use rosenpass_secret_memory::{
|
||||
secret_policy_try_use_memfd_secrets, secret_policy_use_only_malloc_secrets,
|
||||
};
|
||||
use rosenpass_util::file::{LoadValue, LoadValueB64};
|
||||
use rosenpass_util::file::{LoadValue, LoadValueB64, StoreValue};
|
||||
use rosenpass_wireguard_broker::brokers::native_unix::{
|
||||
NativeUnixBroker, NativeUnixBrokerConfigBaseBuilder, NativeUnixBrokerConfigBaseBuilderError,
|
||||
};
|
||||
@@ -370,7 +370,7 @@ impl CliCommand {
|
||||
fn generate_and_save_keypair(secret_key: PathBuf, public_key: PathBuf) -> anyhow::Result<()> {
|
||||
let mut ssk = crate::protocol::SSk::random();
|
||||
let mut spk = crate::protocol::SPk::random();
|
||||
StaticKem::keygen(ssk.secret_mut(), spk.secret_mut())?;
|
||||
StaticKem::keygen(ssk.secret_mut(), &mut *spk)?;
|
||||
ssk.store_secret(secret_key)?;
|
||||
spk.store(public_key)
|
||||
}
|
||||
|
||||
@@ -32,11 +32,11 @@
|
||||
//!
|
||||
//! // initialize secret and public key for peer a ...
|
||||
//! let (mut peer_a_sk, mut peer_a_pk) = (SSk::zero(), SPk::zero());
|
||||
//! StaticKem::keygen(peer_a_sk.secret_mut(), peer_a_pk.secret_mut())?;
|
||||
//! StaticKem::keygen(peer_a_sk.secret_mut(), &mut *peer_a_pk)?;
|
||||
//!
|
||||
//! // ... and for peer b
|
||||
//! let (mut peer_b_sk, mut peer_b_pk) = (SSk::zero(), SPk::zero());
|
||||
//! StaticKem::keygen(peer_b_sk.secret_mut(), peer_b_pk.secret_mut())?;
|
||||
//! StaticKem::keygen(peer_b_sk.secret_mut(), &mut *peer_b_pk)?;
|
||||
//!
|
||||
//! // initialize server and a pre-shared key
|
||||
//! let psk = SymKey::random();
|
||||
@@ -88,7 +88,7 @@ use rosenpass_ciphers::hash_domain::{SecretHashDomain, SecretHashDomainNamespace
|
||||
use rosenpass_ciphers::kem::{EphemeralKem, StaticKem};
|
||||
use rosenpass_ciphers::{aead, xaead, KEY_LEN};
|
||||
use rosenpass_constant_time as constant_time;
|
||||
use rosenpass_secret_memory::{Public, Secret};
|
||||
use rosenpass_secret_memory::{Public, PublicBox, Secret};
|
||||
use rosenpass_util::{cat, mem::cpy_min, ord::max_usize, time::Timebase};
|
||||
use zerocopy::{AsBytes, FromBytes, Ref};
|
||||
|
||||
@@ -163,7 +163,7 @@ pub fn has_happened(ev: Timing, now: Timing) -> bool {
|
||||
|
||||
// DATA STRUCTURES & BASIC TRAITS & ACCESSORS ////
|
||||
|
||||
pub type SPk = Secret<{ StaticKem::PK_LEN }>; // Just Secret<> instead of Public<> so it gets allocated on the heap
|
||||
pub type SPk = PublicBox<{ StaticKem::PK_LEN }>;
|
||||
pub type SSk = Secret<{ StaticKem::SK_LEN }>;
|
||||
pub type EPk = Public<{ EphemeralKem::PK_LEN }>;
|
||||
pub type ESk = Secret<{ EphemeralKem::SK_LEN }>;
|
||||
@@ -548,7 +548,7 @@ impl CryptoServer {
|
||||
pub fn pidm(&self) -> Result<PeerId> {
|
||||
Ok(Public::new(
|
||||
hash_domains::peerid()?
|
||||
.mix(self.spkm.secret())?
|
||||
.mix(&*self.spkm)?
|
||||
.into_value()))
|
||||
}
|
||||
|
||||
@@ -708,7 +708,7 @@ impl Peer {
|
||||
pub fn pidt(&self) -> Result<PeerId> {
|
||||
Ok(Public::new(
|
||||
hash_domains::peerid()?
|
||||
.mix(self.spkt.secret())?
|
||||
.mix(&*self.spkt)?
|
||||
.into_value()))
|
||||
}
|
||||
}
|
||||
@@ -1016,9 +1016,7 @@ impl CryptoServer {
|
||||
);
|
||||
|
||||
let cookie_value = active_cookie_value.unwrap();
|
||||
let cookie_key = hash_domains::cookie_key()?
|
||||
.mix(self.spkm.secret())?
|
||||
.into_value();
|
||||
let cookie_key = hash_domains::cookie_key()?.mix(&*self.spkm)?.into_value();
|
||||
|
||||
let mut msg_out = truncating_cast_into::<CookieReply>(tx_buf)?;
|
||||
|
||||
@@ -1509,7 +1507,7 @@ where
|
||||
/// Calculate the message authentication code (`mac`) and also append cookie value
|
||||
pub fn seal(&mut self, peer: PeerPtr, srv: &CryptoServer) -> Result<()> {
|
||||
let mac = hash_domains::mac()?
|
||||
.mix(peer.get(srv).spkt.secret())?
|
||||
.mix(&*peer.get(srv).spkt)?
|
||||
.mix(&self.as_bytes()[span_of!(Self, msg_type..mac)])?;
|
||||
self.mac.copy_from_slice(mac.into_value()[..16].as_ref());
|
||||
self.seal_cookie(peer, srv)?;
|
||||
@@ -1536,7 +1534,7 @@ where
|
||||
/// Check the message authentication code
|
||||
pub fn check_seal(&self, srv: &CryptoServer) -> Result<bool> {
|
||||
let expected = hash_domains::mac()?
|
||||
.mix(srv.spkm.secret())?
|
||||
.mix(&*srv.spkm)?
|
||||
.mix(&self.as_bytes()[span_of!(Self, msg_type..mac)])?;
|
||||
Ok(constant_time::memcmp(
|
||||
&self.mac,
|
||||
@@ -1641,7 +1639,7 @@ impl HandshakeState {
|
||||
|
||||
// calculate ad contents
|
||||
let ad = hash_domains::biscuit_ad()?
|
||||
.mix(srv.spkm.secret())?
|
||||
.mix(&*srv.spkm)?
|
||||
.mix(self.sidi.as_slice())?
|
||||
.mix(self.sidr.as_slice())?
|
||||
.into_value();
|
||||
@@ -1676,7 +1674,7 @@ impl HandshakeState {
|
||||
|
||||
// Calculate additional data fields
|
||||
let ad = hash_domains::biscuit_ad()?
|
||||
.mix(srv.spkm.secret())?
|
||||
.mix(&*srv.spkm)?
|
||||
.mix(sidi.as_slice())?
|
||||
.mix(sidr.as_slice())?
|
||||
.into_value();
|
||||
@@ -1763,7 +1761,7 @@ impl CryptoServer {
|
||||
let mut hs = InitiatorHandshake::zero_with_timestamp(self);
|
||||
|
||||
// IHI1
|
||||
hs.core.init(peer.get(self).spkt.secret())?;
|
||||
hs.core.init(&*peer.get(self).spkt)?;
|
||||
|
||||
// IHI2
|
||||
hs.core.sidi.randomize();
|
||||
@@ -1780,7 +1778,7 @@ impl CryptoServer {
|
||||
hs.core
|
||||
.encaps_and_mix::<StaticKem, { StaticKem::SHK_LEN }>(
|
||||
ih.sctr.as_mut_slice(),
|
||||
peer.get(self).spkt.secret(),
|
||||
&*peer.get(self).spkt,
|
||||
)?;
|
||||
|
||||
// IHI6
|
||||
@@ -1788,9 +1786,7 @@ impl CryptoServer {
|
||||
.encrypt_and_mix(ih.pidic.as_mut_slice(), self.pidm()?.as_ref())?;
|
||||
|
||||
// IHI7
|
||||
hs.core
|
||||
.mix(self.spkm.secret())?
|
||||
.mix(peer.get(self).psk.secret())?;
|
||||
hs.core.mix(&*self.spkm)?.mix(peer.get(self).psk.secret())?;
|
||||
|
||||
// IHI8
|
||||
hs.core.encrypt_and_mix(ih.auth.as_mut_slice(), &[])?;
|
||||
@@ -1807,7 +1803,7 @@ impl CryptoServer {
|
||||
core.sidi = SessionId::from_slice(&ih.sidi);
|
||||
|
||||
// IHR1
|
||||
core.init(self.spkm.secret())?;
|
||||
core.init(&*self.spkm)?;
|
||||
|
||||
// IHR4
|
||||
core.mix(&ih.sidi)?.mix(&ih.epki)?;
|
||||
@@ -1815,7 +1811,7 @@ impl CryptoServer {
|
||||
// IHR5
|
||||
core.decaps_and_mix::<StaticKem, { StaticKem::SHK_LEN }>(
|
||||
self.sskm.secret(),
|
||||
self.spkm.secret(),
|
||||
&*self.spkm,
|
||||
&ih.sctr,
|
||||
)?;
|
||||
|
||||
@@ -1828,7 +1824,7 @@ impl CryptoServer {
|
||||
};
|
||||
|
||||
// IHR7
|
||||
core.mix(peer.get(self).spkt.secret())?
|
||||
core.mix(&*peer.get(self).spkt)?
|
||||
.mix(peer.get(self).psk.secret())?;
|
||||
|
||||
// IHR8
|
||||
@@ -1848,7 +1844,7 @@ impl CryptoServer {
|
||||
// RHR5
|
||||
core.encaps_and_mix::<StaticKem, { StaticKem::SHK_LEN }>(
|
||||
&mut rh.scti,
|
||||
peer.get(self).spkt.secret(),
|
||||
&*peer.get(self).spkt,
|
||||
)?;
|
||||
|
||||
// RHR6
|
||||
@@ -1916,7 +1912,7 @@ impl CryptoServer {
|
||||
// RHI5
|
||||
core.decaps_and_mix::<StaticKem, { StaticKem::SHK_LEN }>(
|
||||
self.sskm.secret(),
|
||||
self.spkm.secret(),
|
||||
&*self.spkm,
|
||||
&rh.scti,
|
||||
)?;
|
||||
|
||||
@@ -2113,7 +2109,7 @@ impl CryptoServer {
|
||||
),
|
||||
}?;
|
||||
|
||||
let spkt = peer.get(self).spkt.secret();
|
||||
let spkt = &*peer.get(self).spkt;
|
||||
let cookie_key = hash_domains::cookie_key()?.mix(spkt)?.into_value();
|
||||
let cookie_value = peer.cv().update_mut(self).unwrap();
|
||||
|
||||
@@ -2255,7 +2251,7 @@ mod test {
|
||||
fn keygen() -> Result<(SSk, SPk)> {
|
||||
// TODO: Copied from the benchmark; deduplicate
|
||||
let (mut sk, mut pk) = (SSk::zero(), SPk::zero());
|
||||
StaticKem::keygen(sk.secret_mut(), pk.secret_mut())?;
|
||||
StaticKem::keygen(sk.secret_mut(), &mut *pk)?;
|
||||
Ok((sk, pk))
|
||||
}
|
||||
|
||||
|
||||
@@ -5,7 +5,7 @@ use std::{
|
||||
};
|
||||
|
||||
use anyhow::{anyhow, Result};
|
||||
use rosenpass_util::file::{LoadValueB64, StoreValueB64};
|
||||
use rosenpass_util::file::{LoadValueB64, StoreValue, StoreValueB64};
|
||||
use zeroize::Zeroize;
|
||||
|
||||
use rosenpass::protocol::{SPk, SSk};
|
||||
@@ -56,8 +56,8 @@ pub fn genkey(private_keys_dir: &Path) -> Result<()> {
|
||||
if !pqsk_path.exists() && !pqpk_path.exists() {
|
||||
let mut pqsk = SSk::random();
|
||||
let mut pqpk = SPk::random();
|
||||
StaticKem::keygen(pqsk.secret_mut(), pqpk.secret_mut())?;
|
||||
pqpk.store_secret(pqpk_path)?;
|
||||
StaticKem::keygen(pqsk.secret_mut(), &mut *pqpk)?;
|
||||
pqpk.store(pqpk_path)?;
|
||||
pqsk.store_secret(pqsk_path)?;
|
||||
} else {
|
||||
eprintln!(
|
||||
|
||||
@@ -6,6 +6,7 @@ pub mod alloc;
|
||||
|
||||
mod public;
|
||||
pub use crate::public::Public;
|
||||
pub use crate::public::PublicBox;
|
||||
|
||||
mod secret;
|
||||
pub use crate::secret::Secret;
|
||||
|
||||
@@ -277,3 +277,152 @@ mod tests {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Hash, PartialEq, Eq, PartialOrd, Ord)]
|
||||
#[repr(transparent)]
|
||||
pub struct PublicBox<const N: usize> {
|
||||
pub inner: Box<Public<N>>,
|
||||
}
|
||||
|
||||
impl<const N: usize> PublicBox<N> {
|
||||
/// Create a new [Public] from a byte slice
|
||||
pub fn from_slice(value: &[u8]) -> Self {
|
||||
copy_slice(value).to_this(Self::zero) // TODO: fix
|
||||
}
|
||||
|
||||
/// Create a new [Public] from a byte array
|
||||
pub fn new(value: [u8; N]) -> Self {
|
||||
Self {
|
||||
inner: Box::new(Public::new(value)),
|
||||
}
|
||||
}
|
||||
|
||||
/// Create a zero initialized [Public]
|
||||
pub fn zero() -> Self {
|
||||
Self {
|
||||
inner: Box::new(Public::zero()),
|
||||
}
|
||||
}
|
||||
|
||||
/// 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) {
|
||||
(**self).try_fill(&mut crate::rand::rng()).unwrap()
|
||||
}
|
||||
}
|
||||
|
||||
impl<const N: usize> Randomize for PublicBox<N> {
|
||||
fn try_fill<R: Rng + ?Sized>(&mut self, rng: &mut R) -> Result<(), rand::Error> {
|
||||
(**self).try_fill(rng)
|
||||
}
|
||||
}
|
||||
|
||||
impl<const N: usize> fmt::Debug for PublicBox<N> {
|
||||
fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
|
||||
debug_crypto_array(&**self, fmt)
|
||||
}
|
||||
}
|
||||
|
||||
impl<const N: usize> Deref for PublicBox<N> {
|
||||
type Target = [u8; N];
|
||||
|
||||
fn deref(&self) -> &[u8; N] {
|
||||
&*self.inner
|
||||
}
|
||||
}
|
||||
|
||||
impl<const N: usize> DerefMut for PublicBox<N> {
|
||||
fn deref_mut(&mut self) -> &mut [u8; N] {
|
||||
&mut *self.inner
|
||||
}
|
||||
}
|
||||
|
||||
impl<const N: usize> Borrow<[u8]> for PublicBox<N> {
|
||||
fn borrow(&self) -> &[u8] {
|
||||
&**self
|
||||
}
|
||||
}
|
||||
|
||||
impl<const N: usize> BorrowMut<[u8]> for PublicBox<N> {
|
||||
fn borrow_mut(&mut self) -> &mut [u8] {
|
||||
&mut **self
|
||||
}
|
||||
}
|
||||
|
||||
impl<const N: usize> LoadValue for PublicBox<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 PublicBox<N> {
|
||||
type Error = anyhow::Error;
|
||||
|
||||
fn store<P: AsRef<Path>>(&self, path: P) -> anyhow::Result<()> {
|
||||
std::fs::write(path, **self)?;
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
impl<const N: usize> LoadValueB64 for PublicBox<N> {
|
||||
type Error = anyhow::Error;
|
||||
|
||||
fn load_b64<const F: usize, P: AsRef<Path>>(path: P) -> Result<Self, Self::Error>
|
||||
where
|
||||
Self: Sized,
|
||||
{
|
||||
let mut f = [0u8; F];
|
||||
let mut v = PublicBox::zero();
|
||||
let p = path.as_ref();
|
||||
|
||||
let len = fopen_r(p)?
|
||||
.read_slice_to_end(&mut f)
|
||||
.with_context(|| format!("Could not load file {p:?}"))?;
|
||||
|
||||
b64_decode(&f[0..len], &mut *v)
|
||||
.with_context(|| format!("Could not decode base64 file {p:?}"))?;
|
||||
|
||||
Ok(v)
|
||||
}
|
||||
}
|
||||
|
||||
impl<const N: usize> StoreValueB64 for PublicBox<N> {
|
||||
type Error = anyhow::Error;
|
||||
|
||||
fn store_b64<const F: usize, P: AsRef<Path>>(&self, path: P) -> anyhow::Result<()> {
|
||||
let p = path.as_ref();
|
||||
let mut f = [0u8; F];
|
||||
let encoded_str = b64_encode(&**self, &mut f)
|
||||
.with_context(|| format!("Could not encode base64 file {p:?}"))?;
|
||||
fopen_w(p, Visibility::Public)?
|
||||
.write_all(encoded_str.as_bytes())
|
||||
.with_context(|| format!("Could not write file {p:?}"))?;
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
impl<const N: usize> StoreValueB64Writer for PublicBox<N> {
|
||||
type Error = anyhow::Error;
|
||||
|
||||
fn store_b64_writer<const F: usize, W: std::io::Write>(
|
||||
&self,
|
||||
mut writer: W,
|
||||
) -> Result<(), Self::Error> {
|
||||
let mut f = [0u8; F];
|
||||
let encoded_str =
|
||||
b64_encode(&**self, &mut f).with_context(|| "Could not encode secret to base64")?;
|
||||
|
||||
writer
|
||||
.write_all(encoded_str.as_bytes())
|
||||
.with_context(|| "Could not write base64 to writer")?;
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user