Compare commits

..

1 Commits

Author SHA1 Message Date
wucke13
3131441b68 [wip] redo of retransmission handling 2023-04-09 19:09:28 +02:00
4 changed files with 66 additions and 121 deletions

2
Cargo.lock generated
View File

@@ -865,7 +865,7 @@ checksum = "3582f63211428f83597b51b2ddb88e2a91a9d52d12831f9d08f5e624e8977422"
[[package]]
name = "rosenpass"
version = "0.1.2-rc.4"
version = "0.1.1"
dependencies = [
"anyhow",
"base64",

View File

@@ -1,6 +1,6 @@
[package]
name = "rosenpass"
version = "0.1.2-rc.4"
version = "0.1.1"
authors = ["Karolin Varner <karo@cupdev.net>", "wucke13 <wucke13@gmail.com>"]
edition = "2021"
license = "MIT OR Apache-2.0"

View File

@@ -1,105 +0,0 @@
.Dd $Mdocdate$
.Dt ROSENPASS 1
.Os
.Sh NAME
.Nm rosenpass
.Nd builds post-quantum-secure VPNs
.Sh SYNOPSIS
.Nm
.Op COMMAND
.Op Ar OPTIONS ...
.Op Ar ARGS ...
.Sh DESCRIPTION
.Nm
performs cryptographic key exchanges that are secure against quantum-computers
and outputs the keys.
These keys can then be passed to various services such as wireguard or other
vpn services as pre-shared-keys to achieve security against attackers with
quantum computers.
.Pp
This is a research project and quantum computers are not thought to become
practical in less than ten years.
If you are not specifically tasked with developing post-quantum secure systems,
you probably do not need this tool.
.Ss COMMANDS
.Bl -tag -width Ds
.It Ar keygen private-key <file-path> public-key <file-path>
Generate a keypair to use in the exchange command later.
Send the public-key file to your communication partner and keep the private-key
file secret!
.It Ar exchange private-key <file-path> public-key <file-path> [ OPTIONS ] PEERS
Start a process to exchange keys with the specified peers.
You should specify at least one peer.
.Pp
It's
.Ar OPTIONS
are as follows:
.Bl -tag -width Ds
.It Ar listen <ip>[:<port>]
Instructs
.Nm
to listen on the specified interface and port.
By default
.Nm
will listen on all interfaces and select a random port.
.It Ar verbose
Extra logging.
.El
.El
.Ss PEER
Each
.Ar PEER
is defined as follows:
.Qq peer public-key <file-path> [endpoint <ip>[:<port>]] [preshared-key <file-path>] [outfile <file-path>] [wireguard <dev> <peer> <extra_params>]
.Pp
Providing a
.Ar PEER
instructs
.Nm
to exchange keys with the given peer and write the resulting PSK into the given
output file.
You must either specify the outfile or wireguard output option.
.Pp
The parameters of
.Ar PEER
are as follows:
.Bl -tag -width Ds
.It Ar endpoint <ip>[:<port>]
Specifies the address where the peer can be reached.
This will be automatically updated after the first successful key exchange with
the peer.
If this is unspecified, the peer must initiate the connection.
.It Ar preshared-key <file-path>
You may specify a pre-shared key which will be mixed into the final secret.
.It Ar outfile <file-path>
You may specify a file to write the exchanged keys to.
If this option is specified,
.Nm
will write a notification to standard out every time the key is updated.
.It Ar wireguard <dev> <peer> <extra_params>
This allows you to directly specify a wireguard peer to deploy the
pre-shared-key to.
You may specify extra parameters you would pass to
.Qq wg set
besides the preshared-key parameter which is used by
.Nm .
This makes it possible to add peers entirely from
.Nm .
.El
.Sh EXIT STATUS
.Ex -std
.Sh SEE ALSO
.Xr rp 1 ,
.Xr wg 1
.Sh STANDARDS
This tool is the reference implementation of the Rosenpass protocol, written
by Karolin Varner, Benjamin Lipp, Wanja Zaeske, and Lisa Schmidt.
.Sh AUTHORS
Rosenpass was created by Karolin Varner, Benjamin Lipp, Wanja Zaeske,
Marei Peischl, Stephan Ajuvo, and Lisa Schmidt.
.Pp
This manual page was written by
.An Emil Engler
.Sh BUGS
The bugs are tracked at
.Lk https://github.com/rosenpass/rosenpass/issues .

View File

@@ -90,6 +90,7 @@ pub const RTX_BUFFER_SIZE: usize = max_usize(
);
/// A type for time, e.g. for backoff before re-tries
// TODO replace by core::time::Duration
pub type Timing = f64;
/// Before Common Era (or more practically: Definitely so old it needs refreshing)
@@ -209,6 +210,7 @@ pub struct Peer {
pub session: Option<Session>,
pub handshake: Option<InitiatorHandshake>,
pub initiation_requested: bool,
pub th: TransmissionHandler,
}
impl Peer {
@@ -220,6 +222,7 @@ impl Peer {
session: None,
initiation_requested: false,
handshake: None,
th: TransmissionHandler::default(),
}
}
}
@@ -280,6 +283,36 @@ pub struct InitiatorHandshake {
pub tx_buf: MsgBuf,
}
#[derive(Debug)]
pub struct TransmissionHandler {
// when to attempt the first transmission
tx_at: Timing,
// average interval between transmission and subsequent retransmissions
tx_interval: Timing,
// how often to attemp (re-) transmission
tx_count: u8,
// length of message in `tx_buf`
tx_len: usize,
// buffer for the message
tx_buf: MsgBuf,
}
impl Default for TransmissionHandler {
fn default() -> Self {
Self {
tx_at: 0.0,
tx_interval: 1.0,
tx_count: 0,
tx_len: 0,
tx_buf: Public::zero(),
}
}
}
#[derive(Debug)]
pub struct Session {
// Metadata
@@ -460,10 +493,10 @@ impl CryptoServer {
}
#[rustfmt::skip]
pub fn pidm(&self) -> Result<PeerId> {
pub fn pidm(spkm: &[u8]) -> Result<PeerId> {
Ok(Public::new(
lprf::peerid()?
.mix(self.spkm.secret())?
.mix(spkm)?
.into_value()))
}
@@ -484,6 +517,7 @@ impl CryptoServer {
session: None,
handshake: None,
initiation_requested: false,
th: TransmissionHandler::default(),
};
let peerid = peer.pidt()?;
let peerno = self.peers.len();
@@ -586,6 +620,7 @@ impl Peer {
session: None,
handshake: None,
initiation_requested: false,
th: TransmissionHandler::default(),
}
}
@@ -725,7 +760,15 @@ impl CryptoServer {
// TODO remove unecessary copying between global tx_buf and per-peer buf
// TODO move retransmission storage to io server
pub fn initiate_handshake(&mut self, peer: PeerPtr, tx_buf: &mut [u8]) -> Result<usize> {
let mut msg = tx_buf.envelope::<InitHello<()>>()?; // Envelope::<InitHello>::default(); // TODO
let mut msg = tx_buf.envelope::<InitHello<()>>()?;
// Envelope::<InitHello>::default(); // TODO
// let mut msg = peer
// .get_mut(self)
// .th
// .tx_buf
// .as_mut_slice()
// .envelope::<InitHello<()>>()?;
self.handle_initiation(peer, msg.payload_mut().init_hello()?)?;
let len = self.seal_and_commit_msg(peer, MsgType::InitHello, msg)?;
peer.hs()
@@ -781,7 +824,6 @@ impl CryptoServer {
Ok(MsgType::InitHello) => {
let msg_in = rx_buf.envelope::<InitHello<&[u8]>>()?;
ensure!(msg_in.check_seal(self)?, seal_broken);
let mut msg_out = tx_buf.envelope::<RespHello<&mut [u8]>>()?;
let peer = self.handle_init_hello(
msg_in.payload().init_hello()?,
@@ -916,6 +958,9 @@ pub enum PollResult {
DeleteKey(PeerPtr),
SendInitiation(PeerPtr),
SendRetransmission(PeerPtr),
// Transmit(PeerPtr),
// /// implicitly respond to peerptr with msg in scratch_buf
// Respond
}
impl Default for PollResult {
@@ -1394,13 +1439,18 @@ impl CryptoServer {
/// established primitives
pub fn handle_initiation(
&mut self,
peer: PeerPtr,
mut ih: InitHello<&mut [u8]>,
peer_ptr: PeerPtr,
_ih: InitHello<&mut [u8]>,
) -> Result<PeerPtr> {
let mut hs = InitiatorHandshake::zero_with_timestamp(self);
let peer = &mut self.peers[peer_ptr.0];
let mut tx_buf = peer.th.tx_buf;
let mut msg = tx_buf.as_mut_slice().envelope::<InitHello<()>>()?;
peer.th.tx_len = msg.all_bytes().len();
let mut ih = msg.payload_mut().init_hello()?;
// IHI1
hs.core.init(peer.get(self).spkt.secret())?;
hs.core.init(peer.spkt.secret())?;
// IHI2
hs.core.sidi.randomize();
@@ -1417,25 +1467,23 @@ impl CryptoServer {
hs.core
.encaps_and_mix::<StaticKEM, { StaticKEM::SHK_LEN }>(
ih.sctr_mut(),
peer.get(self).spkt.secret(),
peer.spkt.secret(),
)?;
// IHI6
hs.core
.encrypt_and_mix(ih.pidic_mut(), self.pidm()?.as_ref())?;
.encrypt_and_mix(ih.pidic_mut(), Self::pidm(self.spkm.secret())?.as_ref())?;
// IHI7
hs.core
.mix(self.spkm.secret())?
.mix(peer.get(self).psk.secret())?;
hs.core.mix(self.spkm.secret())?.mix(peer.psk.secret())?;
// IHI8
hs.core.encrypt_and_mix(ih.auth_mut(), &NOTHING)?;
// Update the handshake hash last (not changing any state on prior error
peer.hs().insert(self, hs)?;
peer.handshake.insert(hs);
Ok(peer)
Ok(peer_ptr)
}
pub fn handle_init_hello(
@@ -1475,6 +1523,8 @@ impl CryptoServer {
// IHR8
core.decrypt_and_mix(&mut [0u8; 0], ih.auth())?;
// TODO access this peers transmission_handler, bind it as `rh`
// RHR1
core.sidr.randomize();
rh.sidi_mut().copy_from_slice(core.sidi.as_ref());