mirror of
https://github.com/rosenpass/rosenpass.git
synced 2025-12-19 05:44:38 +03:00
Compare commits
2 Commits
v0.2.0-rc.
...
dev/refine
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
63ff75b93c | ||
|
|
5bebdd9284 |
@@ -33,7 +33,7 @@ let systems_map = {
|
|||||||
# aarch64-linux
|
# aarch64-linux
|
||||||
|
|
||||||
i686-linux: ubuntu-latest,
|
i686-linux: ubuntu-latest,
|
||||||
x86_64-darwin: macos-13,
|
x86_64-darwin: macos-latest,
|
||||||
x86_64-linux: ubuntu-latest
|
x86_64-linux: ubuntu-latest
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -64,7 +64,7 @@ let runner_setup = [
|
|||||||
uses: "actions/checkout@v3"
|
uses: "actions/checkout@v3"
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
uses: "cachix/install-nix-action@v22",
|
uses: "cachix/install-nix-action@v21",
|
||||||
with: { nix_path: "nixpkgs=channel:nixos-unstable" }
|
with: { nix_path: "nixpkgs=channel:nixos-unstable" }
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
|
|||||||
52
.github/workflows/nix.yaml
vendored
52
.github/workflows/nix.yaml
vendored
@@ -15,7 +15,7 @@ jobs:
|
|||||||
- i686-linux---rosenpass
|
- i686-linux---rosenpass
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v3
|
- uses: actions/checkout@v3
|
||||||
- uses: cachix/install-nix-action@v22
|
- uses: cachix/install-nix-action@v21
|
||||||
with:
|
with:
|
||||||
nix_path: nixpkgs=channel:nixos-unstable
|
nix_path: nixpkgs=channel:nixos-unstable
|
||||||
- uses: cachix/cachix-action@v12
|
- uses: cachix/cachix-action@v12
|
||||||
@@ -31,7 +31,7 @@ jobs:
|
|||||||
needs: []
|
needs: []
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v3
|
- uses: actions/checkout@v3
|
||||||
- uses: cachix/install-nix-action@v22
|
- uses: cachix/install-nix-action@v21
|
||||||
with:
|
with:
|
||||||
nix_path: nixpkgs=channel:nixos-unstable
|
nix_path: nixpkgs=channel:nixos-unstable
|
||||||
- uses: cachix/cachix-action@v12
|
- uses: cachix/cachix-action@v12
|
||||||
@@ -48,7 +48,7 @@ jobs:
|
|||||||
- i686-linux---rosenpass
|
- i686-linux---rosenpass
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v3
|
- uses: actions/checkout@v3
|
||||||
- uses: cachix/install-nix-action@v22
|
- uses: cachix/install-nix-action@v21
|
||||||
with:
|
with:
|
||||||
nix_path: nixpkgs=channel:nixos-unstable
|
nix_path: nixpkgs=channel:nixos-unstable
|
||||||
- uses: cachix/cachix-action@v12
|
- uses: cachix/cachix-action@v12
|
||||||
@@ -63,7 +63,7 @@ jobs:
|
|||||||
- ubuntu-latest
|
- ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v3
|
- uses: actions/checkout@v3
|
||||||
- uses: cachix/install-nix-action@v22
|
- uses: cachix/install-nix-action@v21
|
||||||
with:
|
with:
|
||||||
nix_path: nixpkgs=channel:nixos-unstable
|
nix_path: nixpkgs=channel:nixos-unstable
|
||||||
- uses: cachix/cachix-action@v12
|
- uses: cachix/cachix-action@v12
|
||||||
@@ -75,12 +75,12 @@ jobs:
|
|||||||
x86_64-darwin---default:
|
x86_64-darwin---default:
|
||||||
name: Build x86_64-darwin.default
|
name: Build x86_64-darwin.default
|
||||||
runs-on:
|
runs-on:
|
||||||
- macos-13
|
- macos-latest
|
||||||
needs:
|
needs:
|
||||||
- x86_64-darwin---rosenpass
|
- x86_64-darwin---rosenpass
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v3
|
- uses: actions/checkout@v3
|
||||||
- uses: cachix/install-nix-action@v22
|
- uses: cachix/install-nix-action@v21
|
||||||
with:
|
with:
|
||||||
nix_path: nixpkgs=channel:nixos-unstable
|
nix_path: nixpkgs=channel:nixos-unstable
|
||||||
- uses: cachix/cachix-action@v12
|
- uses: cachix/cachix-action@v12
|
||||||
@@ -92,13 +92,13 @@ jobs:
|
|||||||
x86_64-darwin---release-package:
|
x86_64-darwin---release-package:
|
||||||
name: Build x86_64-darwin.release-package
|
name: Build x86_64-darwin.release-package
|
||||||
runs-on:
|
runs-on:
|
||||||
- macos-13
|
- macos-latest
|
||||||
needs:
|
needs:
|
||||||
- x86_64-darwin---rosenpass
|
- x86_64-darwin---rosenpass
|
||||||
- x86_64-darwin---rosenpass-oci-image
|
- x86_64-darwin---rosenpass-oci-image
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v3
|
- uses: actions/checkout@v3
|
||||||
- uses: cachix/install-nix-action@v22
|
- uses: cachix/install-nix-action@v21
|
||||||
with:
|
with:
|
||||||
nix_path: nixpkgs=channel:nixos-unstable
|
nix_path: nixpkgs=channel:nixos-unstable
|
||||||
- uses: cachix/cachix-action@v12
|
- uses: cachix/cachix-action@v12
|
||||||
@@ -110,11 +110,11 @@ jobs:
|
|||||||
x86_64-darwin---rosenpass:
|
x86_64-darwin---rosenpass:
|
||||||
name: Build x86_64-darwin.rosenpass
|
name: Build x86_64-darwin.rosenpass
|
||||||
runs-on:
|
runs-on:
|
||||||
- macos-13
|
- macos-latest
|
||||||
needs: []
|
needs: []
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v3
|
- uses: actions/checkout@v3
|
||||||
- uses: cachix/install-nix-action@v22
|
- uses: cachix/install-nix-action@v21
|
||||||
with:
|
with:
|
||||||
nix_path: nixpkgs=channel:nixos-unstable
|
nix_path: nixpkgs=channel:nixos-unstable
|
||||||
- uses: cachix/cachix-action@v12
|
- uses: cachix/cachix-action@v12
|
||||||
@@ -126,12 +126,12 @@ jobs:
|
|||||||
x86_64-darwin---rosenpass-oci-image:
|
x86_64-darwin---rosenpass-oci-image:
|
||||||
name: Build x86_64-darwin.rosenpass-oci-image
|
name: Build x86_64-darwin.rosenpass-oci-image
|
||||||
runs-on:
|
runs-on:
|
||||||
- macos-13
|
- macos-latest
|
||||||
needs:
|
needs:
|
||||||
- x86_64-darwin---rosenpass
|
- x86_64-darwin---rosenpass
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v3
|
- uses: actions/checkout@v3
|
||||||
- uses: cachix/install-nix-action@v22
|
- uses: cachix/install-nix-action@v21
|
||||||
with:
|
with:
|
||||||
nix_path: nixpkgs=channel:nixos-unstable
|
nix_path: nixpkgs=channel:nixos-unstable
|
||||||
- uses: cachix/cachix-action@v12
|
- uses: cachix/cachix-action@v12
|
||||||
@@ -143,10 +143,10 @@ jobs:
|
|||||||
x86_64-darwin---check:
|
x86_64-darwin---check:
|
||||||
name: Run Nix checks on x86_64-darwin
|
name: Run Nix checks on x86_64-darwin
|
||||||
runs-on:
|
runs-on:
|
||||||
- macos-13
|
- macos-latest
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v3
|
- uses: actions/checkout@v3
|
||||||
- uses: cachix/install-nix-action@v22
|
- uses: cachix/install-nix-action@v21
|
||||||
with:
|
with:
|
||||||
nix_path: nixpkgs=channel:nixos-unstable
|
nix_path: nixpkgs=channel:nixos-unstable
|
||||||
- uses: cachix/cachix-action@v12
|
- uses: cachix/cachix-action@v12
|
||||||
@@ -163,7 +163,7 @@ jobs:
|
|||||||
- x86_64-linux---rosenpass
|
- x86_64-linux---rosenpass
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v3
|
- uses: actions/checkout@v3
|
||||||
- uses: cachix/install-nix-action@v22
|
- uses: cachix/install-nix-action@v21
|
||||||
with:
|
with:
|
||||||
nix_path: nixpkgs=channel:nixos-unstable
|
nix_path: nixpkgs=channel:nixos-unstable
|
||||||
- uses: cachix/cachix-action@v12
|
- uses: cachix/cachix-action@v12
|
||||||
@@ -180,7 +180,7 @@ jobs:
|
|||||||
- x86_64-linux---proverif-patched
|
- x86_64-linux---proverif-patched
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v3
|
- uses: actions/checkout@v3
|
||||||
- uses: cachix/install-nix-action@v22
|
- uses: cachix/install-nix-action@v21
|
||||||
with:
|
with:
|
||||||
nix_path: nixpkgs=channel:nixos-unstable
|
nix_path: nixpkgs=channel:nixos-unstable
|
||||||
- uses: cachix/cachix-action@v12
|
- uses: cachix/cachix-action@v12
|
||||||
@@ -196,7 +196,7 @@ jobs:
|
|||||||
needs: []
|
needs: []
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v3
|
- uses: actions/checkout@v3
|
||||||
- uses: cachix/install-nix-action@v22
|
- uses: cachix/install-nix-action@v21
|
||||||
with:
|
with:
|
||||||
nix_path: nixpkgs=channel:nixos-unstable
|
nix_path: nixpkgs=channel:nixos-unstable
|
||||||
- uses: cachix/cachix-action@v12
|
- uses: cachix/cachix-action@v12
|
||||||
@@ -210,11 +210,11 @@ jobs:
|
|||||||
runs-on:
|
runs-on:
|
||||||
- ubuntu-latest
|
- ubuntu-latest
|
||||||
needs:
|
needs:
|
||||||
- x86_64-linux---rosenpass-static-oci-image
|
|
||||||
- x86_64-linux---rosenpass-static
|
- x86_64-linux---rosenpass-static
|
||||||
|
- x86_64-linux---rosenpass-static-oci-image
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v3
|
- uses: actions/checkout@v3
|
||||||
- uses: cachix/install-nix-action@v22
|
- uses: cachix/install-nix-action@v21
|
||||||
with:
|
with:
|
||||||
nix_path: nixpkgs=channel:nixos-unstable
|
nix_path: nixpkgs=channel:nixos-unstable
|
||||||
- uses: cachix/cachix-action@v12
|
- uses: cachix/cachix-action@v12
|
||||||
@@ -230,7 +230,7 @@ jobs:
|
|||||||
needs: []
|
needs: []
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v3
|
- uses: actions/checkout@v3
|
||||||
- uses: cachix/install-nix-action@v22
|
- uses: cachix/install-nix-action@v21
|
||||||
with:
|
with:
|
||||||
nix_path: nixpkgs=channel:nixos-unstable
|
nix_path: nixpkgs=channel:nixos-unstable
|
||||||
- uses: cachix/cachix-action@v12
|
- uses: cachix/cachix-action@v12
|
||||||
@@ -247,7 +247,7 @@ jobs:
|
|||||||
- x86_64-linux---rosenpass
|
- x86_64-linux---rosenpass
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v3
|
- uses: actions/checkout@v3
|
||||||
- uses: cachix/install-nix-action@v22
|
- uses: cachix/install-nix-action@v21
|
||||||
with:
|
with:
|
||||||
nix_path: nixpkgs=channel:nixos-unstable
|
nix_path: nixpkgs=channel:nixos-unstable
|
||||||
- uses: cachix/cachix-action@v12
|
- uses: cachix/cachix-action@v12
|
||||||
@@ -263,7 +263,7 @@ jobs:
|
|||||||
needs: []
|
needs: []
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v3
|
- uses: actions/checkout@v3
|
||||||
- uses: cachix/install-nix-action@v22
|
- uses: cachix/install-nix-action@v21
|
||||||
with:
|
with:
|
||||||
nix_path: nixpkgs=channel:nixos-unstable
|
nix_path: nixpkgs=channel:nixos-unstable
|
||||||
- uses: cachix/cachix-action@v12
|
- uses: cachix/cachix-action@v12
|
||||||
@@ -280,7 +280,7 @@ jobs:
|
|||||||
- x86_64-linux---rosenpass-static
|
- x86_64-linux---rosenpass-static
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v3
|
- uses: actions/checkout@v3
|
||||||
- uses: cachix/install-nix-action@v22
|
- uses: cachix/install-nix-action@v21
|
||||||
with:
|
with:
|
||||||
nix_path: nixpkgs=channel:nixos-unstable
|
nix_path: nixpkgs=channel:nixos-unstable
|
||||||
- uses: cachix/cachix-action@v12
|
- uses: cachix/cachix-action@v12
|
||||||
@@ -296,7 +296,7 @@ jobs:
|
|||||||
needs: []
|
needs: []
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v3
|
- uses: actions/checkout@v3
|
||||||
- uses: cachix/install-nix-action@v22
|
- uses: cachix/install-nix-action@v21
|
||||||
with:
|
with:
|
||||||
nix_path: nixpkgs=channel:nixos-unstable
|
nix_path: nixpkgs=channel:nixos-unstable
|
||||||
- uses: cachix/cachix-action@v12
|
- uses: cachix/cachix-action@v12
|
||||||
@@ -311,7 +311,7 @@ jobs:
|
|||||||
- ubuntu-latest
|
- ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v3
|
- uses: actions/checkout@v3
|
||||||
- uses: cachix/install-nix-action@v22
|
- uses: cachix/install-nix-action@v21
|
||||||
with:
|
with:
|
||||||
nix_path: nixpkgs=channel:nixos-unstable
|
nix_path: nixpkgs=channel:nixos-unstable
|
||||||
- uses: cachix/cachix-action@v12
|
- uses: cachix/cachix-action@v12
|
||||||
@@ -326,7 +326,7 @@ jobs:
|
|||||||
if: ${{ github.ref == 'refs/heads/main' }}
|
if: ${{ github.ref == 'refs/heads/main' }}
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v3
|
- uses: actions/checkout@v3
|
||||||
- uses: cachix/install-nix-action@v22
|
- uses: cachix/install-nix-action@v21
|
||||||
with:
|
with:
|
||||||
nix_path: nixpkgs=channel:nixos-unstable
|
nix_path: nixpkgs=channel:nixos-unstable
|
||||||
- uses: cachix/cachix-action@v12
|
- uses: cachix/cachix-action@v12
|
||||||
|
|||||||
51
.github/workflows/qc.yaml
vendored
51
.github/workflows/qc.yaml
vendored
@@ -17,14 +17,6 @@ jobs:
|
|||||||
with:
|
with:
|
||||||
args: --check .
|
args: --check .
|
||||||
|
|
||||||
shellcheck:
|
|
||||||
name: Shellcheck
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v3
|
|
||||||
- name: Run ShellCheck
|
|
||||||
uses: ludeeus/action-shellcheck@master
|
|
||||||
|
|
||||||
cargo-audit:
|
cargo-audit:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
@@ -74,46 +66,3 @@ jobs:
|
|||||||
# - https://github.com/rosenpass/rosenpass/issues/62
|
# - https://github.com/rosenpass/rosenpass/issues/62
|
||||||
# - https://github.com/rust-lang/rust/issues/108378
|
# - https://github.com/rust-lang/rust/issues/108378
|
||||||
- run: RUSTDOCFLAGS="-D warnings" cargo doc --no-deps --document-private-items
|
- run: RUSTDOCFLAGS="-D warnings" cargo doc --no-deps --document-private-items
|
||||||
|
|
||||||
cargo-test:
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v3
|
|
||||||
- uses: actions/cache@v3
|
|
||||||
with:
|
|
||||||
path: |
|
|
||||||
~/.cargo/bin/
|
|
||||||
~/.cargo/registry/index/
|
|
||||||
~/.cargo/registry/cache/
|
|
||||||
~/.cargo/git/db/
|
|
||||||
target/
|
|
||||||
key: ${{ runner.os }}-cargo-${{ hashFiles('**/Cargo.lock') }}
|
|
||||||
- name: Install libsodium
|
|
||||||
run: sudo apt-get install -y libsodium-dev
|
|
||||||
# liboqs requires quite a lot of stack memory, thus we adjust
|
|
||||||
# the default stack size picked for new threads (which is used
|
|
||||||
# by `cargo test`) to be _big enough_. Setting it to 8 MiB
|
|
||||||
- run: RUST_MIN_STACK=8388608 cargo test
|
|
||||||
|
|
||||||
cargo-test-nix-devshell-x86_64-linux:
|
|
||||||
runs-on:
|
|
||||||
- ubuntu-latest
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v3
|
|
||||||
- uses: actions/cache@v3
|
|
||||||
with:
|
|
||||||
path: |
|
|
||||||
~/.cargo/bin/
|
|
||||||
~/.cargo/registry/index/
|
|
||||||
~/.cargo/registry/cache/
|
|
||||||
~/.cargo/git/db/
|
|
||||||
target/
|
|
||||||
key: ${{ runner.os }}-cargo-${{ hashFiles('**/Cargo.lock') }}
|
|
||||||
- uses: cachix/install-nix-action@v21
|
|
||||||
with:
|
|
||||||
nix_path: nixpkgs=channel:nixos-unstable
|
|
||||||
- uses: cachix/cachix-action@v12
|
|
||||||
with:
|
|
||||||
name: rosenpass
|
|
||||||
authToken: ${{ secrets.CACHIX_AUTH_TOKEN }}
|
|
||||||
- run: nix develop --command cargo test
|
|
||||||
|
|||||||
8
.github/workflows/release.yaml
vendored
8
.github/workflows/release.yaml
vendored
@@ -12,7 +12,7 @@ jobs:
|
|||||||
- ubuntu-latest
|
- ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v3
|
- uses: actions/checkout@v3
|
||||||
- uses: cachix/install-nix-action@v22
|
- uses: cachix/install-nix-action@v21
|
||||||
with:
|
with:
|
||||||
nix_path: nixpkgs=channel:nixos-unstable
|
nix_path: nixpkgs=channel:nixos-unstable
|
||||||
- uses: cachix/cachix-action@v12
|
- uses: cachix/cachix-action@v12
|
||||||
@@ -30,10 +30,10 @@ jobs:
|
|||||||
x86_64-darwin---release:
|
x86_64-darwin---release:
|
||||||
name: Build release artifacts for x86_64-darwin
|
name: Build release artifacts for x86_64-darwin
|
||||||
runs-on:
|
runs-on:
|
||||||
- macos-13
|
- macos-latest
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v3
|
- uses: actions/checkout@v3
|
||||||
- uses: cachix/install-nix-action@v22
|
- uses: cachix/install-nix-action@v21
|
||||||
with:
|
with:
|
||||||
nix_path: nixpkgs=channel:nixos-unstable
|
nix_path: nixpkgs=channel:nixos-unstable
|
||||||
- uses: cachix/cachix-action@v12
|
- uses: cachix/cachix-action@v12
|
||||||
@@ -54,7 +54,7 @@ jobs:
|
|||||||
- ubuntu-latest
|
- ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v3
|
- uses: actions/checkout@v3
|
||||||
- uses: cachix/install-nix-action@v22
|
- uses: cachix/install-nix-action@v21
|
||||||
with:
|
with:
|
||||||
nix_path: nixpkgs=channel:nixos-unstable
|
nix_path: nixpkgs=channel:nixos-unstable
|
||||||
- uses: cachix/cachix-action@v12
|
- uses: cachix/cachix-action@v12
|
||||||
|
|||||||
@@ -1,17 +0,0 @@
|
|||||||
# TODO use CI_JOB_TOKEN once https://gitlab.com/groups/gitlab-org/-/epics/6310 is fixed
|
|
||||||
pull-from-gh:
|
|
||||||
only: ["schedules"]
|
|
||||||
variables:
|
|
||||||
REMOTE: "https://github.com/rosenpass/rosenpass.git"
|
|
||||||
LOCAL: " git@gitlab.com:rosenpass/rosenpass.git"
|
|
||||||
GIT_STRATEGY: none
|
|
||||||
before_script:
|
|
||||||
- mkdir ~/.ssh/
|
|
||||||
- echo "$SSH_KNOWN_HOSTS" > ~/.ssh/known_hosts
|
|
||||||
- echo "$REPO_SSH_KEY" > ~/.ssh/id_ed25519
|
|
||||||
- chmod 600 --recursive ~/.ssh/
|
|
||||||
- git config --global user.email "ci@gitlab.com"
|
|
||||||
- git config --global user.name "CI"
|
|
||||||
script:
|
|
||||||
- git clone --mirror $REMOTE rosenpass
|
|
||||||
- cd rosenpass && git push --mirror $LOCAL
|
|
||||||
673
Cargo.lock
generated
673
Cargo.lock
generated
File diff suppressed because it is too large
Load Diff
@@ -1,6 +1,6 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "rosenpass"
|
name = "rosenpass"
|
||||||
version = "0.2.0-rc.1"
|
version = "0.1.2-rc.4"
|
||||||
authors = ["Karolin Varner <karo@cupdev.net>", "wucke13 <wucke13@gmail.com>"]
|
authors = ["Karolin Varner <karo@cupdev.net>", "wucke13 <wucke13@gmail.com>"]
|
||||||
edition = "2021"
|
edition = "2021"
|
||||||
license = "MIT OR Apache-2.0"
|
license = "MIT OR Apache-2.0"
|
||||||
@@ -14,12 +14,11 @@ name = "handshake"
|
|||||||
harness = false
|
harness = false
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
anyhow = { version = "1.0.71", features = ["backtrace"] }
|
|
||||||
base64 = "0.21.1"
|
base64 = "0.21.1"
|
||||||
static_assertions = "1.1.0"
|
static_assertions = "1.1.0"
|
||||||
memoffset = "0.9.0"
|
memoffset = "0.9.0"
|
||||||
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.7.2", default-features = false, features = ['classic_mceliece', 'kyber'] }
|
||||||
lazy_static = "1.4.0"
|
lazy_static = "1.4.0"
|
||||||
thiserror = "1.0.40"
|
thiserror = "1.0.40"
|
||||||
paste = "1.0.12"
|
paste = "1.0.12"
|
||||||
|
|||||||
30
flake.lock
generated
30
flake.lock
generated
@@ -8,11 +8,11 @@
|
|||||||
"rust-analyzer-src": "rust-analyzer-src"
|
"rust-analyzer-src": "rust-analyzer-src"
|
||||||
},
|
},
|
||||||
"locked": {
|
"locked": {
|
||||||
"lastModified": 1692771621,
|
"lastModified": 1686291735,
|
||||||
"narHash": "sha256-W1qOIeOvzkJxdITGGWqSxmFbu9ob+ZP8lXNkkQi8UL4=",
|
"narHash": "sha256-mpq2m6TN3ImqqUqA4u93NvkZu5vH//3spqjmPRbRlvA=",
|
||||||
"owner": "nix-community",
|
"owner": "nix-community",
|
||||||
"repo": "fenix",
|
"repo": "fenix",
|
||||||
"rev": "add522038f2a32aa1263c8d3c81e1ea2265cc4e1",
|
"rev": "6e6a94c4d0cac4821b6452fbae46609b89a8ddcf",
|
||||||
"type": "github"
|
"type": "github"
|
||||||
},
|
},
|
||||||
"original": {
|
"original": {
|
||||||
@@ -26,11 +26,11 @@
|
|||||||
"systems": "systems"
|
"systems": "systems"
|
||||||
},
|
},
|
||||||
"locked": {
|
"locked": {
|
||||||
"lastModified": 1689068808,
|
"lastModified": 1685518550,
|
||||||
"narHash": "sha256-6ixXo3wt24N/melDWjq70UuHQLxGV8jZvooRanIHXw0=",
|
"narHash": "sha256-o2d0KcvaXzTrPRIo0kOLV0/QXHhDQ5DTi+OxcjO8xqY=",
|
||||||
"owner": "numtide",
|
"owner": "numtide",
|
||||||
"repo": "flake-utils",
|
"repo": "flake-utils",
|
||||||
"rev": "919d646de7be200f3bf08cb76ae1f09402b6f9b4",
|
"rev": "a1720a10a6cfe8234c0e93907ffe81be440f4cef",
|
||||||
"type": "github"
|
"type": "github"
|
||||||
},
|
},
|
||||||
"original": {
|
"original": {
|
||||||
@@ -46,11 +46,11 @@
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
"locked": {
|
"locked": {
|
||||||
"lastModified": 1692351612,
|
"lastModified": 1679567394,
|
||||||
"narHash": "sha256-KTGonidcdaLadRnv9KFgwSMh1ZbXoR/OBmPjeNMhFwU=",
|
"narHash": "sha256-ZvLuzPeARDLiQUt6zSZFGOs+HZmE+3g4QURc8mkBsfM=",
|
||||||
"owner": "nix-community",
|
"owner": "nix-community",
|
||||||
"repo": "naersk",
|
"repo": "naersk",
|
||||||
"rev": "78789c30d64dea2396c9da516bbcc8db3a475207",
|
"rev": "88cd22380154a2c36799fe8098888f0f59861a15",
|
||||||
"type": "github"
|
"type": "github"
|
||||||
},
|
},
|
||||||
"original": {
|
"original": {
|
||||||
@@ -61,11 +61,11 @@
|
|||||||
},
|
},
|
||||||
"nixpkgs": {
|
"nixpkgs": {
|
||||||
"locked": {
|
"locked": {
|
||||||
"lastModified": 1691522891,
|
"lastModified": 1686237827,
|
||||||
"narHash": "sha256-xqQqVryXKJoFQ/+RL0A7DihkLkev8dk6afM7B04TilU=",
|
"narHash": "sha256-fAZB+Zkcmc+qlauiFnIH9+2qgwM0NO/ru5pWEw3tDow=",
|
||||||
"owner": "NixOS",
|
"owner": "NixOS",
|
||||||
"repo": "nixpkgs",
|
"repo": "nixpkgs",
|
||||||
"rev": "78287547942dd8e8afff0ae47fb8e2553db79d7e",
|
"rev": "81ed90058a851eb73be835c770e062c6938c8a9e",
|
||||||
"type": "github"
|
"type": "github"
|
||||||
},
|
},
|
||||||
"original": {
|
"original": {
|
||||||
@@ -84,11 +84,11 @@
|
|||||||
"rust-analyzer-src": {
|
"rust-analyzer-src": {
|
||||||
"flake": false,
|
"flake": false,
|
||||||
"locked": {
|
"locked": {
|
||||||
"lastModified": 1692701491,
|
"lastModified": 1686239338,
|
||||||
"narHash": "sha256-Lz5GXi/CImvcIXtpBpQ9jVI9Ni9eU/4xk36PvKmjwJM=",
|
"narHash": "sha256-c6Mm7UnDf3j3akY3YB3rELFA76QRbB8ttSBsh00LWi0=",
|
||||||
"owner": "rust-lang",
|
"owner": "rust-lang",
|
||||||
"repo": "rust-analyzer",
|
"repo": "rust-analyzer",
|
||||||
"rev": "9e3bf69ad3c736893b285f47f4d014ae1aed1cb0",
|
"rev": "9c03aa1ac2e67051db83a85baf3cfee902e4dd84",
|
||||||
"type": "github"
|
"type": "github"
|
||||||
},
|
},
|
||||||
"original": {
|
"original": {
|
||||||
|
|||||||
@@ -71,13 +71,6 @@ Rosenpass is packaged for more and more distributions, maybe also for the distri
|
|||||||
|
|
||||||
[](https://repology.org/project/rosenpass/versions)
|
[](https://repology.org/project/rosenpass/versions)
|
||||||
|
|
||||||
# Mirrors
|
|
||||||
|
|
||||||
Don't want to use GitHub or only have an IPv6 connection? Rosenpass has set up two mirrors for this:
|
|
||||||
|
|
||||||
- [NotABug](https://notabug.org/rosenpass/rosenpass)
|
|
||||||
- [GitLab](https://gitlab.com/rosenpass/rosenpass/)
|
|
||||||
|
|
||||||
# Supported by
|
# Supported by
|
||||||
|
|
||||||
Funded through <a href="https://nlnet.nl/">NLNet</a> with financial support for the European Commission's <a href="https://nlnet.nl/assure">NGI Assure</a> program.
|
Funded through <a href="https://nlnet.nl/">NLNet</a> with financial support for the European Commission's <a href="https://nlnet.nl/assure">NGI Assure</a> program.
|
||||||
|
|||||||
48
rp
48
rp
@@ -197,7 +197,7 @@ exchange() {
|
|||||||
lip="${listen%:*}";
|
lip="${listen%:*}";
|
||||||
lport="${listen/*:/}";
|
lport="${listen/*:/}";
|
||||||
if [[ "$lip" = "$lport" ]]; then
|
if [[ "$lip" = "$lport" ]]; then
|
||||||
lip="[::]"
|
lip="[0::0]"
|
||||||
fi
|
fi
|
||||||
shift;;
|
shift;;
|
||||||
-h | -help | --help | help) usage; return 0;;
|
-h | -help | --help | help) usage; return 0;;
|
||||||
@@ -209,41 +209,15 @@ exchange() {
|
|||||||
fatal "Needs at least one peer specified"
|
fatal "Needs at least one peer specified"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# os dependent setup
|
frag "
|
||||||
case "$OSTYPE" in
|
# Create the Wireguard interface
|
||||||
linux-*) # could be linux-gnu or linux-musl
|
ip link add dev $(enquote "${dev}") type wireguard || true"
|
||||||
frag "
|
|
||||||
# Create the WireGuard interface
|
|
||||||
ip link add dev $(enquote "${dev}") type wireguard || true"
|
|
||||||
|
|
||||||
cleanup "
|
cleanup "
|
||||||
ip link del dev $(enquote "${dev}") || true"
|
ip link del dev $(enquote "${dev}") || true"
|
||||||
|
|
||||||
frag "
|
frag "
|
||||||
ip link set dev $(enquote "${dev}") up"
|
ip link set dev $(enquote "${dev}") up"
|
||||||
;;
|
|
||||||
|
|
||||||
freebsd*)
|
|
||||||
frag "
|
|
||||||
# load the WireGuard kernel module
|
|
||||||
kldload -n if_wg || fatal 'Cannot load if_wg kernel module'"
|
|
||||||
|
|
||||||
frag "
|
|
||||||
# Create the WireGuard interface
|
|
||||||
ifconfig wg create name $(enquote "${dev}") || true"
|
|
||||||
|
|
||||||
cleanup "
|
|
||||||
ifconfig $(enquote "${dev}") destroy || true"
|
|
||||||
|
|
||||||
frag "
|
|
||||||
ifconfig $(enquote "${dev}") up"
|
|
||||||
;;
|
|
||||||
|
|
||||||
*)
|
|
||||||
fatal "Your system $OSTYPE is not yet supported. We are happy to receive patches to address this :)"
|
|
||||||
;;
|
|
||||||
|
|
||||||
esac
|
|
||||||
|
|
||||||
frag "
|
frag "
|
||||||
# Deploy the classic wireguard private key
|
# Deploy the classic wireguard private key
|
||||||
@@ -281,7 +255,7 @@ exchange() {
|
|||||||
local arg; arg="$1"; shift
|
local arg; arg="$1"; shift
|
||||||
case "${arg}" in
|
case "${arg}" in
|
||||||
peer) set -- "peer" "$@"; break;; # Next peer
|
peer) set -- "peer" "$@"; break;; # Next peer
|
||||||
endpoint) ip="${1%:*}"; port="${1##*:}"; shift;;
|
endpoint) ip="${1%:*}"; port="${1/*:/}"; shift;;
|
||||||
persistent-keepalive) keepalive="${1}"; shift;;
|
persistent-keepalive) keepalive="${1}"; shift;;
|
||||||
allowed-ips) allowedips="${1}"; shift;;
|
allowed-ips) allowedips="${1}"; shift;;
|
||||||
-h | -help | --help | help) usage; return 0;;
|
-h | -help | --help | help) usage; return 0;;
|
||||||
@@ -352,9 +326,7 @@ main() {
|
|||||||
verbose=0
|
verbose=0
|
||||||
scriptdir="$(dirname "${script}")"
|
scriptdir="$(dirname "${script}")"
|
||||||
gitdir="$(detect_git_dir)" || true
|
gitdir="$(detect_git_dir)" || true
|
||||||
if [[ -d /nix ]]; then
|
nixdir="$(readlink -f result/bin/rp | grep -Pio '^/nix/store/[^/]+(?=/bin/[^/]+)')" || true
|
||||||
nixdir="$(readlink -f result/bin/rp | grep -Pio '^/nix/store/[^/]+(?=/bin/[^/]+)')" || true
|
|
||||||
fi
|
|
||||||
binary="$(find_rosenpass_binary)"
|
binary="$(find_rosenpass_binary)"
|
||||||
|
|
||||||
# Parse command
|
# Parse command
|
||||||
|
|||||||
@@ -1,6 +1,3 @@
|
|||||||
use anyhow::bail;
|
|
||||||
|
|
||||||
use anyhow::Result;
|
|
||||||
use log::{error, info, warn};
|
use log::{error, info, warn};
|
||||||
use mio::Interest;
|
use mio::Interest;
|
||||||
use mio::Token;
|
use mio::Token;
|
||||||
@@ -22,10 +19,12 @@ use std::slice;
|
|||||||
use std::time::Duration;
|
use std::time::Duration;
|
||||||
|
|
||||||
use crate::util::fopen_w;
|
use crate::util::fopen_w;
|
||||||
|
use crate::RosenpassError;
|
||||||
use crate::{
|
use crate::{
|
||||||
config::Verbosity,
|
config::Verbosity,
|
||||||
protocol::{CryptoServer, MsgBuf, PeerPtr, SPk, SSk, SymKey, Timing},
|
protocol::{CryptoServer, MsgBuf, PeerPtr, SPk, SSk, SymKey, Timing},
|
||||||
util::{b64_writer, fmt_b64},
|
util::{b64_writer, fmt_b64},
|
||||||
|
Result,
|
||||||
};
|
};
|
||||||
|
|
||||||
const IPV4_ANY_ADDR: Ipv4Addr = Ipv4Addr::new(0, 0, 0, 0);
|
const IPV4_ANY_ADDR: Ipv4Addr = Ipv4Addr::new(0, 0, 0, 0);
|
||||||
@@ -98,7 +97,7 @@ impl SocketPtr {
|
|||||||
&mut srv.sockets[self.0]
|
&mut srv.sockets[self.0]
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn send_to(&self, srv: &AppServer, buf: &[u8], addr: SocketAddr) -> anyhow::Result<()> {
|
pub fn send_to(&self, srv: &AppServer, buf: &[u8], addr: SocketAddr) -> Result<()> {
|
||||||
self.get(srv).send_to(&buf, addr)?;
|
self.get(srv).send_to(&buf, addr)?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
@@ -181,7 +180,7 @@ impl Endpoint {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Start endpoint discovery from a hostname
|
/// Start endpoint discovery from a hostname
|
||||||
pub fn discovery_from_hostname(hostname: String) -> anyhow::Result<Self> {
|
pub fn discovery_from_hostname(hostname: String) -> Result<Self> {
|
||||||
let host = HostPathDiscoveryEndpoint::lookup(hostname)?;
|
let host = HostPathDiscoveryEndpoint::lookup(hostname)?;
|
||||||
Ok(Endpoint::Discovery(host))
|
Ok(Endpoint::Discovery(host))
|
||||||
}
|
}
|
||||||
@@ -211,7 +210,7 @@ impl Endpoint {
|
|||||||
Some(Self::discovery_from_addresses(addrs))
|
Some(Self::discovery_from_addresses(addrs))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn send(&self, srv: &AppServer, buf: &[u8]) -> anyhow::Result<()> {
|
pub fn send(&self, srv: &AppServer, buf: &[u8]) -> Result<()> {
|
||||||
use Endpoint::*;
|
use Endpoint::*;
|
||||||
match self {
|
match self {
|
||||||
SocketBoundAddress { socket, addr } => socket.send_to(srv, buf, *addr),
|
SocketBoundAddress { socket, addr } => socket.send_to(srv, buf, *addr),
|
||||||
@@ -270,7 +269,7 @@ impl HostPathDiscoveryEndpoint {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Lookup a hostname
|
/// Lookup a hostname
|
||||||
pub fn lookup(hostname: String) -> anyhow::Result<Self> {
|
pub fn lookup(hostname: String) -> Result<Self> {
|
||||||
Ok(Self {
|
Ok(Self {
|
||||||
addresses: ToSocketAddrs::to_socket_addrs(&hostname)?.collect(),
|
addresses: ToSocketAddrs::to_socket_addrs(&hostname)?.collect(),
|
||||||
scouting_state: Cell::new((0, 0)),
|
scouting_state: Cell::new((0, 0)),
|
||||||
@@ -291,7 +290,7 @@ impl HostPathDiscoveryEndpoint {
|
|||||||
/// Attempt to reach the host
|
/// Attempt to reach the host
|
||||||
///
|
///
|
||||||
/// Will round-robin-try different socket-ip-combinations on each call.
|
/// Will round-robin-try different socket-ip-combinations on each call.
|
||||||
pub fn send_scouting(&self, srv: &AppServer, buf: &[u8]) -> anyhow::Result<()> {
|
pub fn send_scouting(&self, srv: &AppServer, buf: &[u8]) -> Result<()> {
|
||||||
let (addr_off, sock_off) = self.scouting_state.get();
|
let (addr_off, sock_off) = self.scouting_state.get();
|
||||||
|
|
||||||
let mut addrs = (&self.addresses)
|
let mut addrs = (&self.addresses)
|
||||||
@@ -330,23 +329,19 @@ impl HostPathDiscoveryEndpoint {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bail!("Unable to send message: All sockets returned errors.")
|
error!("Unable to send message: All sockets returned errors.");
|
||||||
|
return Err(RosenpassError::RuntimeError);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl AppServer {
|
impl AppServer {
|
||||||
pub fn new(
|
pub fn new(sk: SSk, pk: SPk, addrs: Vec<SocketAddr>, verbosity: Verbosity) -> Result<Self> {
|
||||||
sk: SSk,
|
|
||||||
pk: SPk,
|
|
||||||
addrs: Vec<SocketAddr>,
|
|
||||||
verbosity: Verbosity,
|
|
||||||
) -> anyhow::Result<Self> {
|
|
||||||
// setup mio
|
// setup mio
|
||||||
let mio_poll = mio::Poll::new()?;
|
let mio_poll = mio::Poll::new()?;
|
||||||
let events = mio::Events::with_capacity(8);
|
let events = mio::Events::with_capacity(8);
|
||||||
|
|
||||||
// bind each SocketAddr to a socket
|
// bind each SocketAddr to a socket
|
||||||
let maybe_sockets: Result<Vec<_>, _> =
|
let maybe_sockets: std::result::Result<Vec<_>, std::io::Error> =
|
||||||
addrs.into_iter().map(mio::net::UdpSocket::bind).collect();
|
addrs.into_iter().map(mio::net::UdpSocket::bind).collect();
|
||||||
let mut sockets = maybe_sockets?;
|
let mut sockets = maybe_sockets?;
|
||||||
|
|
||||||
@@ -413,7 +408,8 @@ impl AppServer {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if sockets.is_empty() {
|
if sockets.is_empty() {
|
||||||
bail!("No sockets to listen on!")
|
error!("No sockets to listen on!");
|
||||||
|
return Err(RosenpassError::RuntimeError);
|
||||||
}
|
}
|
||||||
|
|
||||||
// register all sockets to mio
|
// register all sockets to mio
|
||||||
@@ -447,7 +443,7 @@ impl AppServer {
|
|||||||
outfile: Option<PathBuf>,
|
outfile: Option<PathBuf>,
|
||||||
outwg: Option<WireguardOut>,
|
outwg: Option<WireguardOut>,
|
||||||
hostname: Option<String>,
|
hostname: Option<String>,
|
||||||
) -> anyhow::Result<AppPeerPtr> {
|
) -> Result<AppPeerPtr> {
|
||||||
let PeerPtr(pn) = self.crypt.add_peer(psk, pk)?;
|
let PeerPtr(pn) = self.crypt.add_peer(psk, pk)?;
|
||||||
assert!(pn == self.peers.len());
|
assert!(pn == self.peers.len());
|
||||||
let initial_endpoint = hostname
|
let initial_endpoint = hostname
|
||||||
@@ -463,7 +459,7 @@ impl AppServer {
|
|||||||
Ok(AppPeerPtr(pn))
|
Ok(AppPeerPtr(pn))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn listen_loop(&mut self) -> anyhow::Result<()> {
|
pub fn listen_loop(&mut self) -> Result<()> {
|
||||||
const INIT_SLEEP: f64 = 0.01;
|
const INIT_SLEEP: f64 = 0.01;
|
||||||
const MAX_FAILURES: i32 = 10;
|
const MAX_FAILURES: i32 = 10;
|
||||||
let mut failure_cnt = 0;
|
let mut failure_cnt = 0;
|
||||||
@@ -484,10 +480,11 @@ impl AppServer {
|
|||||||
let sleep = INIT_SLEEP * 2.0f64.powf(f64::from(failure_cnt - 1));
|
let sleep = INIT_SLEEP * 2.0f64.powf(f64::from(failure_cnt - 1));
|
||||||
let tries_left = MAX_FAILURES - (failure_cnt - 1);
|
let tries_left = MAX_FAILURES - (failure_cnt - 1);
|
||||||
error!(
|
error!(
|
||||||
"unexpected error after processing {} messages: {:?} {}",
|
"unexpected error after processing {} messages: {:?}",
|
||||||
msgs_processed,
|
msgs_processed,
|
||||||
err,
|
err,
|
||||||
err.backtrace()
|
// TODO do we need backtraces?
|
||||||
|
// err.backtrace()
|
||||||
);
|
);
|
||||||
if tries_left > 0 {
|
if tries_left > 0 {
|
||||||
error!("re-initializing networking in {sleep}! {tries_left} tries left.");
|
error!("re-initializing networking in {sleep}! {tries_left} tries left.");
|
||||||
@@ -495,11 +492,12 @@ impl AppServer {
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
bail!("too many network failures");
|
error!("too many network failures");
|
||||||
|
return Err(RosenpassError::RuntimeError);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn event_loop(&mut self) -> anyhow::Result<()> {
|
pub fn event_loop(&mut self) -> Result<()> {
|
||||||
let (mut rx, mut tx) = (MsgBuf::zero(), MsgBuf::zero());
|
let (mut rx, mut tx) = (MsgBuf::zero(), MsgBuf::zero());
|
||||||
|
|
||||||
/// if socket address for peer is known, call closure
|
/// if socket address for peer is known, call closure
|
||||||
@@ -548,11 +546,9 @@ impl AppServer {
|
|||||||
match self.crypt.handle_msg(&rx[..len], &mut *tx) {
|
match self.crypt.handle_msg(&rx[..len], &mut *tx) {
|
||||||
Err(ref e) => {
|
Err(ref e) => {
|
||||||
self.verbose().then(|| {
|
self.verbose().then(|| {
|
||||||
info!(
|
error!(
|
||||||
"error processing incoming message from {:?}: {:?} {}",
|
"error processing incoming message from {:?}: {:?}",
|
||||||
endpoint,
|
endpoint, e
|
||||||
e,
|
|
||||||
e.backtrace()
|
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -580,12 +576,7 @@ impl AppServer {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn output_key(
|
pub fn output_key(&self, peer: AppPeerPtr, why: KeyOutputReason, key: &SymKey) -> Result<()> {
|
||||||
&self,
|
|
||||||
peer: AppPeerPtr,
|
|
||||||
why: KeyOutputReason,
|
|
||||||
key: &SymKey,
|
|
||||||
) -> anyhow::Result<()> {
|
|
||||||
let peerid = peer.lower().get(&self.crypt).pidt()?;
|
let peerid = peer.lower().get(&self.crypt).pidt()?;
|
||||||
let ap = peer.get_app(self);
|
let ap = peer.get_app(self);
|
||||||
|
|
||||||
@@ -636,7 +627,7 @@ impl AppServer {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn poll(&mut self, rx_buf: &mut [u8]) -> anyhow::Result<AppPollResult> {
|
pub fn poll(&mut self, rx_buf: &mut [u8]) -> Result<AppPollResult> {
|
||||||
use crate::protocol::PollResult as C;
|
use crate::protocol::PollResult as C;
|
||||||
use AppPollResult as A;
|
use AppPollResult as A;
|
||||||
loop {
|
loop {
|
||||||
@@ -661,7 +652,7 @@ impl AppServer {
|
|||||||
&mut self,
|
&mut self,
|
||||||
buf: &mut [u8],
|
buf: &mut [u8],
|
||||||
timeout: Timing,
|
timeout: Timing,
|
||||||
) -> anyhow::Result<Option<(usize, Endpoint)>> {
|
) -> Result<Option<(usize, Endpoint)>> {
|
||||||
let timeout = Duration::from_secs_f64(timeout);
|
let timeout = Duration::from_secs_f64(timeout);
|
||||||
|
|
||||||
// if there is no time to wait on IO, well, then, lets not waste any time!
|
// if there is no time to wait on IO, well, then, lets not waste any time!
|
||||||
|
|||||||
70
src/cli.rs
70
src/cli.rs
@@ -1,7 +1,3 @@
|
|||||||
use anyhow::{bail, ensure};
|
|
||||||
use clap::Parser;
|
|
||||||
use std::path::{Path, PathBuf};
|
|
||||||
|
|
||||||
use crate::app_server;
|
use crate::app_server;
|
||||||
use crate::app_server::AppServer;
|
use crate::app_server::AppServer;
|
||||||
use crate::util::{LoadValue, LoadValueB64};
|
use crate::util::{LoadValue, LoadValueB64};
|
||||||
@@ -10,7 +6,12 @@ use crate::{
|
|||||||
coloring::Secret,
|
coloring::Secret,
|
||||||
pqkem::{StaticKEM, KEM},
|
pqkem::{StaticKEM, KEM},
|
||||||
protocol::{SPk, SSk, SymKey},
|
protocol::{SPk, SSk, SymKey},
|
||||||
|
Result,
|
||||||
|
RosenpassError,
|
||||||
};
|
};
|
||||||
|
use clap::Parser;
|
||||||
|
use log::error;
|
||||||
|
use std::path::{Path, PathBuf};
|
||||||
|
|
||||||
use super::config;
|
use super::config;
|
||||||
|
|
||||||
@@ -98,25 +99,21 @@ pub enum Cli {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl Cli {
|
impl Cli {
|
||||||
pub fn run() -> anyhow::Result<()> {
|
pub fn run() -> Result<()> {
|
||||||
let cli = Self::parse();
|
let cli = Self::parse();
|
||||||
|
|
||||||
use Cli::*;
|
use Cli::*;
|
||||||
match cli {
|
match cli {
|
||||||
Man => {
|
Man => {
|
||||||
let man_cmd = std::process::Command::new("man")
|
let _man_cmd = std::process::Command::new("man")
|
||||||
.args(["1", "rosenpass"])
|
.args(["1", "rosenpass"])
|
||||||
.status();
|
.status();
|
||||||
|
|
||||||
if !(man_cmd.is_ok() && man_cmd.unwrap().success()) {
|
|
||||||
println!(include_str!(env!("ROSENPASS_MAN")));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
GenConfig { config_file, force } => {
|
GenConfig { config_file, force } => {
|
||||||
ensure!(
|
if !force && config_file.exists() {
|
||||||
force || !config_file.exists(),
|
error!("config file {config_file:?} already exists");
|
||||||
"config file {config_file:?} already exists"
|
return Err(RosenpassError::RuntimeError);
|
||||||
);
|
}
|
||||||
|
|
||||||
config::Rosenpass::example_config().store(config_file)?;
|
config::Rosenpass::example_config().store(config_file)?;
|
||||||
}
|
}
|
||||||
@@ -130,35 +127,34 @@ impl Cli {
|
|||||||
// figure out where the key file is specified, in the config file or directly as flag?
|
// figure out where the key file is specified, in the config file or directly as flag?
|
||||||
let (pkf, skf) = match (config_file, public_key, secret_key) {
|
let (pkf, skf) = match (config_file, public_key, secret_key) {
|
||||||
(Some(config_file), _, _) => {
|
(Some(config_file), _, _) => {
|
||||||
ensure!(
|
if !config_file.exists() {
|
||||||
config_file.exists(),
|
error!("config file {config_file:?} does not exist");
|
||||||
"config file {config_file:?} does not exist"
|
return Err(RosenpassError::RuntimeError);
|
||||||
);
|
}
|
||||||
|
|
||||||
let config = config::Rosenpass::load(config_file)?;
|
let config = config::Rosenpass::load(config_file)?;
|
||||||
|
|
||||||
(config.public_key, config.secret_key)
|
(config.public_key, config.secret_key)
|
||||||
}
|
}
|
||||||
(_, Some(pkf), Some(skf)) => (pkf, skf),
|
(_, Some(pkf), Some(skf)) => (pkf, skf),
|
||||||
_ => {
|
_ => return Err(RosenpassError::ConfigError(
|
||||||
bail!("either a config-file or both public-key and secret-key file are required")
|
"either a config-file or both public-key and secret-key file are required"
|
||||||
}
|
.into(),
|
||||||
|
)),
|
||||||
};
|
};
|
||||||
|
|
||||||
// check that we are not overriding something unintentionally
|
// check that we are not overriding something unintentionally
|
||||||
let mut problems = vec![];
|
let mut problems = false;
|
||||||
if !force && pkf.is_file() {
|
if !force && pkf.is_file() {
|
||||||
problems.push(format!(
|
problems = true;
|
||||||
"public-key file {pkf:?} exist, refusing to overwrite it"
|
error!("public-key file {pkf:?} exist, refusing to overwrite it");
|
||||||
));
|
|
||||||
}
|
}
|
||||||
if !force && skf.is_file() {
|
if !force && skf.is_file() {
|
||||||
problems.push(format!(
|
problems = true;
|
||||||
"secret-key file {skf:?} exist, refusing to overwrite it"
|
error!("secret-key file {skf:?} exist, refusing to overwrite it");
|
||||||
));
|
|
||||||
}
|
}
|
||||||
if !problems.is_empty() {
|
if problems {
|
||||||
bail!(problems.join("\n"));
|
return Err(RosenpassError::RuntimeError);
|
||||||
}
|
}
|
||||||
|
|
||||||
// generate the keys and store them in files
|
// generate the keys and store them in files
|
||||||
@@ -173,10 +169,10 @@ impl Cli {
|
|||||||
}
|
}
|
||||||
|
|
||||||
ExchangeConfig { config_file } => {
|
ExchangeConfig { config_file } => {
|
||||||
ensure!(
|
if !config_file.exists() {
|
||||||
config_file.exists(),
|
error!("config file '{config_file:?}' does not exist");
|
||||||
"config file '{config_file:?}' does not exist"
|
return Err(RosenpassError::RuntimeError);
|
||||||
);
|
}
|
||||||
|
|
||||||
let config = config::Rosenpass::load(config_file)?;
|
let config = config::Rosenpass::load(config_file)?;
|
||||||
config.validate()?;
|
config.validate()?;
|
||||||
@@ -219,7 +215,7 @@ impl Cli {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn event_loop(config: config::Rosenpass) -> anyhow::Result<()> {
|
fn event_loop(config: config::Rosenpass) -> Result<()> {
|
||||||
// load own keys
|
// load own keys
|
||||||
let sk = SSk::load(&config.secret_key)?;
|
let sk = SSk::load(&config.secret_key)?;
|
||||||
let pk = SPk::load(&config.public_key)?;
|
let pk = SPk::load(&config.public_key)?;
|
||||||
@@ -252,11 +248,11 @@ impl Cli {
|
|||||||
}
|
}
|
||||||
|
|
||||||
trait StoreSecret {
|
trait StoreSecret {
|
||||||
unsafe fn store_secret<P: AsRef<Path>>(&self, path: P) -> anyhow::Result<()>;
|
unsafe fn store_secret<P: AsRef<Path>>(&self, path: P) -> Result<()>;
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<const N: usize> StoreSecret for Secret<N> {
|
impl<const N: usize> StoreSecret for Secret<N> {
|
||||||
unsafe fn store_secret<P: AsRef<Path>>(&self, path: P) -> anyhow::Result<()> {
|
unsafe fn store_secret<P: AsRef<Path>>(&self, path: P) -> Result<()> {
|
||||||
std::fs::write(path, self.secret())?;
|
std::fs::write(path, self.secret())?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|||||||
155
src/config.rs
155
src/config.rs
@@ -6,10 +6,10 @@ use std::{
|
|||||||
path::{Path, PathBuf},
|
path::{Path, PathBuf},
|
||||||
};
|
};
|
||||||
|
|
||||||
use anyhow::{bail, ensure};
|
use log::{error, warn};
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
use crate::util::fopen_w;
|
use crate::{util::fopen_w, Result, RosenpassError};
|
||||||
|
|
||||||
#[derive(Debug, Serialize, Deserialize)]
|
#[derive(Debug, Serialize, Deserialize)]
|
||||||
pub struct Rosenpass {
|
pub struct Rosenpass {
|
||||||
@@ -62,7 +62,7 @@ impl Rosenpass {
|
|||||||
/// Load a config file from a file path
|
/// Load a config file from a file path
|
||||||
///
|
///
|
||||||
/// no validation is conducted
|
/// no validation is conducted
|
||||||
pub fn load<P: AsRef<Path>>(p: P) -> anyhow::Result<Self> {
|
pub fn load<P: AsRef<Path>>(p: P) -> Result<Self> {
|
||||||
let mut config: Self = toml::from_str(&fs::read_to_string(&p)?)?;
|
let mut config: Self = toml::from_str(&fs::read_to_string(&p)?)?;
|
||||||
|
|
||||||
config.config_file_path = p.as_ref().to_owned();
|
config.config_file_path = p.as_ref().to_owned();
|
||||||
@@ -70,7 +70,7 @@ impl Rosenpass {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Write a config to a file
|
/// Write a config to a file
|
||||||
pub fn store<P: AsRef<Path>>(&self, p: P) -> anyhow::Result<()> {
|
pub fn store<P: AsRef<Path>>(&self, p: P) -> Result<()> {
|
||||||
let serialized_config =
|
let serialized_config =
|
||||||
toml::to_string_pretty(&self).expect("unable to serialize the default config");
|
toml::to_string_pretty(&self).expect("unable to serialize the default config");
|
||||||
fs::write(p, serialized_config)?;
|
fs::write(p, serialized_config)?;
|
||||||
@@ -78,7 +78,7 @@ impl Rosenpass {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Commit the configuration to where it came from, overwriting the original file
|
/// Commit the configuration to where it came from, overwriting the original file
|
||||||
pub fn commit(&self) -> anyhow::Result<()> {
|
pub fn commit(&self) -> Result<()> {
|
||||||
let mut f = fopen_w(&self.config_file_path)?;
|
let mut f = fopen_w(&self.config_file_path)?;
|
||||||
f.write_all(toml::to_string_pretty(&self)?.as_bytes())?;
|
f.write_all(toml::to_string_pretty(&self)?.as_bytes())?;
|
||||||
|
|
||||||
@@ -86,36 +86,40 @@ impl Rosenpass {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Validate a configuration
|
/// Validate a configuration
|
||||||
pub fn validate(&self) -> anyhow::Result<()> {
|
pub fn validate(&self) -> Result<()> {
|
||||||
// check the public-key file exists
|
// check the public-key file exists
|
||||||
ensure!(
|
if !(self.public_key.is_file()) {
|
||||||
self.public_key.is_file(),
|
return Err(RosenpassError::ConfigError(format!(
|
||||||
"public-key file {:?} does not exist",
|
"public-key file {:?} does not exist",
|
||||||
self.public_key
|
self.public_key
|
||||||
);
|
)));
|
||||||
|
}
|
||||||
|
|
||||||
// check the secret-key file exists
|
// check the secret-key file exists
|
||||||
ensure!(
|
if !(self.secret_key.is_file()) {
|
||||||
self.secret_key.is_file(),
|
return Err(RosenpassError::ConfigError(format!(
|
||||||
"secret-key file {:?} does not exist",
|
"secret-key file {:?} does not exist",
|
||||||
self.secret_key
|
self.secret_key
|
||||||
);
|
)));
|
||||||
|
}
|
||||||
|
|
||||||
for (i, peer) in self.peers.iter().enumerate() {
|
for (i, peer) in self.peers.iter().enumerate() {
|
||||||
// check peer's public-key file exists
|
// check peer's public-key file exists
|
||||||
ensure!(
|
if !(peer.public_key.is_file()) {
|
||||||
peer.public_key.is_file(),
|
return Err(RosenpassError::ConfigError(format!(
|
||||||
"peer {i} public-key file {:?} does not exist",
|
"peer {i} public-key file {:?} does not exist",
|
||||||
peer.public_key
|
peer.public_key
|
||||||
);
|
)));
|
||||||
|
}
|
||||||
|
|
||||||
// check endpoint is usable
|
// check endpoint is usable
|
||||||
if let Some(addr) = peer.endpoint.as_ref() {
|
if let Some(addr) = peer.endpoint.as_ref() {
|
||||||
ensure!(
|
if !(addr.to_socket_addrs().is_ok()) {
|
||||||
addr.to_socket_addrs().is_ok(),
|
return Err(RosenpassError::ConfigError(format!(
|
||||||
"peer {i} endpoint {} can not be parsed to a socket address",
|
"peer {i} endpoint {} can not be parsed to a socket address",
|
||||||
addr
|
addr
|
||||||
);
|
)));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO warn if neither out_key nor exchange_command is defined
|
// TODO warn if neither out_key nor exchange_command is defined
|
||||||
@@ -151,7 +155,7 @@ impl Rosenpass {
|
|||||||
|
|
||||||
/// from chaotic args
|
/// from chaotic args
|
||||||
/// Quest: the grammar is undecideable, what do we do here?
|
/// Quest: the grammar is undecideable, what do we do here?
|
||||||
pub fn parse_args(args: Vec<String>) -> anyhow::Result<Self> {
|
pub fn parse_args(args: Vec<String>) -> Result<Self> {
|
||||||
let mut config = Self::new("", "");
|
let mut config = Self::new("", "");
|
||||||
|
|
||||||
#[derive(Debug, Hash, PartialEq, Eq)]
|
#[derive(Debug, Hash, PartialEq, Eq)]
|
||||||
@@ -174,6 +178,7 @@ impl Rosenpass {
|
|||||||
|
|
||||||
// TODO idea: use config.peers.len() to give index of peer with conflicting argument
|
// TODO idea: use config.peers.len() to give index of peer with conflicting argument
|
||||||
use State::*;
|
use State::*;
|
||||||
|
let mut problem = false;
|
||||||
let mut state = Own;
|
let mut state = Own;
|
||||||
let mut current_peer = None;
|
let mut current_peer = None;
|
||||||
let p_exists = "a peer should exist by now";
|
let p_exists = "a peer should exist by now";
|
||||||
@@ -183,9 +188,7 @@ impl Rosenpass {
|
|||||||
(Own, "public-key", None) => OwnPublicKey,
|
(Own, "public-key", None) => OwnPublicKey,
|
||||||
(Own, "secret-key", None) => OwnSecretKey,
|
(Own, "secret-key", None) => OwnSecretKey,
|
||||||
(Own, "private-key", None) => {
|
(Own, "private-key", None) => {
|
||||||
log::warn!(
|
warn!("the private-key argument is deprecated, please use secret-key instead");
|
||||||
"the private-key argument is deprecated, please use secret-key instead"
|
|
||||||
);
|
|
||||||
OwnSecretKey
|
OwnSecretKey
|
||||||
}
|
}
|
||||||
(Own, "listen", None) => OwnListen,
|
(Own, "listen", None) => OwnListen,
|
||||||
@@ -194,14 +197,16 @@ impl Rosenpass {
|
|||||||
Own
|
Own
|
||||||
}
|
}
|
||||||
(Own, "peer", None) => {
|
(Own, "peer", None) => {
|
||||||
ensure!(
|
if !(already_set.contains(&OwnPublicKey)) {
|
||||||
already_set.contains(&OwnPublicKey),
|
return Err(RosenpassError::ConfigError(
|
||||||
"public-key file must be set"
|
"public-key file must be set".into(),
|
||||||
);
|
));
|
||||||
ensure!(
|
}
|
||||||
already_set.contains(&OwnSecretKey),
|
if !(already_set.contains(&OwnSecretKey)) {
|
||||||
"secret-key file must be set"
|
return Err(RosenpassError::ConfigError(
|
||||||
);
|
"secret-key file must be set".into(),
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
already_set.clear();
|
already_set.clear();
|
||||||
current_peer = Some(RosenpassPeer::default());
|
current_peer = Some(RosenpassPeer::default());
|
||||||
@@ -209,18 +214,20 @@ impl Rosenpass {
|
|||||||
Peer
|
Peer
|
||||||
}
|
}
|
||||||
(OwnPublicKey, pk, None) => {
|
(OwnPublicKey, pk, None) => {
|
||||||
ensure!(
|
if !(already_set.insert(OwnPublicKey)) {
|
||||||
already_set.insert(OwnPublicKey),
|
return Err(RosenpassError::ConfigError(
|
||||||
"public-key was already set"
|
"public-key was already set".into(),
|
||||||
);
|
));
|
||||||
|
}
|
||||||
config.public_key = pk.into();
|
config.public_key = pk.into();
|
||||||
Own
|
Own
|
||||||
}
|
}
|
||||||
(OwnSecretKey, sk, None) => {
|
(OwnSecretKey, sk, None) => {
|
||||||
ensure!(
|
if !(already_set.insert(OwnSecretKey)) {
|
||||||
already_set.insert(OwnSecretKey),
|
return Err(RosenpassError::ConfigError(
|
||||||
"secret-key was already set"
|
"secret-key was already set".into(),
|
||||||
);
|
));
|
||||||
|
}
|
||||||
config.secret_key = sk.into();
|
config.secret_key = sk.into();
|
||||||
Own
|
Own
|
||||||
}
|
}
|
||||||
@@ -248,36 +255,45 @@ impl Rosenpass {
|
|||||||
(Peer, "outfile", Some(_)) => PeerOutfile,
|
(Peer, "outfile", Some(_)) => PeerOutfile,
|
||||||
(Peer, "wireguard", Some(_)) => PeerWireguardDev,
|
(Peer, "wireguard", Some(_)) => PeerWireguardDev,
|
||||||
(PeerPublicKey, pk, Some(peer)) => {
|
(PeerPublicKey, pk, Some(peer)) => {
|
||||||
ensure!(
|
if !(already_set.insert(PeerPublicKey)) {
|
||||||
already_set.insert(PeerPublicKey),
|
return Err(RosenpassError::ConfigError(
|
||||||
"public-key was already set"
|
"public-key was already set".into(),
|
||||||
);
|
));
|
||||||
|
}
|
||||||
peer.public_key = pk.into();
|
peer.public_key = pk.into();
|
||||||
Peer
|
Peer
|
||||||
}
|
}
|
||||||
(PeerEndpoint, e, Some(peer)) => {
|
(PeerEndpoint, e, Some(peer)) => {
|
||||||
ensure!(already_set.insert(PeerEndpoint), "endpoint was already set");
|
if !already_set.insert(PeerEndpoint) {
|
||||||
|
error!("endpoint was already set");
|
||||||
|
problem = true;
|
||||||
|
}
|
||||||
peer.endpoint = Some(e.to_owned());
|
peer.endpoint = Some(e.to_owned());
|
||||||
Peer
|
Peer
|
||||||
}
|
}
|
||||||
(PeerPsk, psk, Some(peer)) => {
|
(PeerPsk, psk, Some(peer)) => {
|
||||||
ensure!(already_set.insert(PeerEndpoint), "peer psk was already set");
|
if !already_set.insert(PeerEndpoint) {
|
||||||
|
error!("peer psk was already set");
|
||||||
|
problem = true;
|
||||||
|
}
|
||||||
peer.pre_shared_key = Some(psk.into());
|
peer.pre_shared_key = Some(psk.into());
|
||||||
Peer
|
Peer
|
||||||
}
|
}
|
||||||
(PeerOutfile, of, Some(peer)) => {
|
(PeerOutfile, of, Some(peer)) => {
|
||||||
ensure!(
|
if !(already_set.insert(PeerOutfile)) {
|
||||||
already_set.insert(PeerOutfile),
|
return Err(RosenpassError::ConfigError(
|
||||||
"peer outfile was already set"
|
"peer outfile was already set".into(),
|
||||||
);
|
));
|
||||||
|
}
|
||||||
peer.key_out = Some(of.into());
|
peer.key_out = Some(of.into());
|
||||||
Peer
|
Peer
|
||||||
}
|
}
|
||||||
(PeerWireguardDev, dev, Some(peer)) => {
|
(PeerWireguardDev, dev, Some(peer)) => {
|
||||||
ensure!(
|
if !(already_set.insert(PeerWireguardDev)) {
|
||||||
already_set.insert(PeerWireguardDev),
|
return Err(RosenpassError::ConfigError(
|
||||||
"peer wireguard-dev was already set"
|
"peer wireguard-dev was already set".into(),
|
||||||
);
|
));
|
||||||
|
}
|
||||||
assert!(peer.wg.is_none());
|
assert!(peer.wg.is_none());
|
||||||
peer.wg = Some(WireGuard {
|
peer.wg = Some(WireGuard {
|
||||||
device: dev.to_string(),
|
device: dev.to_string(),
|
||||||
@@ -287,10 +303,11 @@ impl Rosenpass {
|
|||||||
PeerWireguardPeer
|
PeerWireguardPeer
|
||||||
}
|
}
|
||||||
(PeerWireguardPeer, p, Some(peer)) => {
|
(PeerWireguardPeer, p, Some(peer)) => {
|
||||||
ensure!(
|
if !(already_set.insert(PeerWireguardPeer)) {
|
||||||
already_set.insert(PeerWireguardPeer),
|
return Err(RosenpassError::ConfigError(
|
||||||
"peer wireguard-peer was already set"
|
"peer wireguard-peer was already set".into(),
|
||||||
);
|
));
|
||||||
|
}
|
||||||
peer.wg.as_mut().expect(wg_exists).peer = p.to_string();
|
peer.wg.as_mut().expect(wg_exists).peer = p.to_string();
|
||||||
PeerWireguardExtraArgs
|
PeerWireguardExtraArgs
|
||||||
}
|
}
|
||||||
@@ -305,14 +322,16 @@ impl Rosenpass {
|
|||||||
|
|
||||||
// error cases
|
// error cases
|
||||||
(Own, x, None) => {
|
(Own, x, None) => {
|
||||||
bail!("unrecognised argument {x}");
|
error!("unrecognised argument {x}");
|
||||||
|
return Err(RosenpassError::RuntimeError);
|
||||||
}
|
}
|
||||||
(Own | OwnPublicKey | OwnSecretKey | OwnListen, _, Some(_)) => {
|
(Own | OwnPublicKey | OwnSecretKey | OwnListen, _, Some(_)) => {
|
||||||
panic!("current_peer is not None while in Own* state, this must never happen")
|
panic!("current_peer is not None while in Own* state, this must never happen")
|
||||||
}
|
}
|
||||||
|
|
||||||
(State::Peer, arg, Some(_)) => {
|
(State::Peer, arg, Some(_)) => {
|
||||||
bail!("unrecongnised argument {arg}");
|
error!("unrecongnised argument {arg}");
|
||||||
|
return Err(RosenpassError::RuntimeError);
|
||||||
}
|
}
|
||||||
(
|
(
|
||||||
Peer
|
Peer
|
||||||
@@ -331,6 +350,10 @@ impl Rosenpass {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if problem {
|
||||||
|
return Err(RosenpassError::RuntimeError);
|
||||||
|
}
|
||||||
|
|
||||||
if let Some(p) = current_peer {
|
if let Some(p) = current_peer {
|
||||||
// TODO ensure peer is propagated with sufficient information
|
// TODO ensure peer is propagated with sufficient information
|
||||||
config.peers.push(p);
|
config.peers.push(p);
|
||||||
|
|||||||
@@ -2,8 +2,8 @@
|
|||||||
//! ensures their uniqueness
|
//! ensures their uniqueness
|
||||||
|
|
||||||
use {
|
use {
|
||||||
|
crate::Result,
|
||||||
crate::{prftree::PrfTree, sodium::KEY_SIZE},
|
crate::{prftree::PrfTree, sodium::KEY_SIZE},
|
||||||
anyhow::Result,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
pub fn protocol() -> Result<PrfTree> {
|
pub fn protocol() -> Result<PrfTree> {
|
||||||
@@ -21,12 +21,12 @@ macro_rules! prflabel {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
prflabel!(protocol, mac, "mac");
|
prflabel!(protocol, mac, "mac");
|
||||||
prflabel!(protocol, cookie, "cookie");
|
prflabel!(protocol, cookie, "cookie");
|
||||||
prflabel!(protocol, peerid, "peer id");
|
prflabel!(protocol, peerid, "peer id");
|
||||||
prflabel!(protocol, biscuit_ad, "biscuit additional data");
|
prflabel!(protocol, biscuit_ad, "biscuit additional data");
|
||||||
prflabel!(protocol, ckinit, "chaining key init");
|
prflabel!(protocol, ckinit, "chaining key init");
|
||||||
prflabel!(protocol, _ckextract, "chaining key extract");
|
prflabel!(protocol, _ckextract, "chaining key extract");
|
||||||
|
|
||||||
macro_rules! prflabel_leaf {
|
macro_rules! prflabel_leaf {
|
||||||
($base:ident, $name:ident, $($lbl:expr),* ) => {
|
($base:ident, $name:ident, $($lbl:expr),* ) => {
|
||||||
@@ -38,10 +38,10 @@ macro_rules! prflabel_leaf {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
prflabel_leaf!(_ckextract, mix, "mix");
|
prflabel_leaf!(_ckextract, mix, "mix");
|
||||||
prflabel_leaf!(_ckextract, hs_enc, "handshake encryption");
|
prflabel_leaf!(_ckextract, hs_enc, "handshake encryption");
|
||||||
prflabel_leaf!(_ckextract, ini_enc, "initiator handshake encryption");
|
prflabel_leaf!(_ckextract, ini_enc, "initiator handshake encryption");
|
||||||
prflabel_leaf!(_ckextract, res_enc, "responder handshake encryption");
|
prflabel_leaf!(_ckextract, res_enc, "responder handshake encryption");
|
||||||
|
|
||||||
prflabel!(_ckextract, _user, "user");
|
prflabel!(_ckextract, _user, "user");
|
||||||
prflabel!(_user, _rp, "rosenpass.eu");
|
prflabel!(_user, _rp, "rosenpass.eu");
|
||||||
|
|||||||
77
src/lib.rs
77
src/lib.rs
@@ -1,3 +1,5 @@
|
|||||||
|
use protocol::{HandshakeStateMachine, PeerId, PeerPtr, SessionId};
|
||||||
|
|
||||||
#[macro_use]
|
#[macro_use]
|
||||||
pub mod util;
|
pub mod util;
|
||||||
#[macro_use]
|
#[macro_use]
|
||||||
@@ -17,20 +19,89 @@ pub mod protocol;
|
|||||||
pub enum RosenpassError {
|
pub enum RosenpassError {
|
||||||
#[error("error in OQS")]
|
#[error("error in OQS")]
|
||||||
Oqs,
|
Oqs,
|
||||||
|
|
||||||
#[error("error from external library while calling OQS")]
|
#[error("error from external library while calling OQS")]
|
||||||
OqsExternalLib,
|
OqsExternalLib,
|
||||||
|
|
||||||
|
#[error("error while calling into libsodium")]
|
||||||
|
LibsodiumError(&'static str),
|
||||||
|
|
||||||
#[error("buffer size mismatch, required {required_size} but only found {actual_size}")]
|
#[error("buffer size mismatch, required {required_size} but only found {actual_size}")]
|
||||||
BufferSizeMismatch {
|
BufferSizeMismatch {
|
||||||
required_size: usize,
|
required_size: usize,
|
||||||
actual_size: usize,
|
actual_size: usize,
|
||||||
},
|
},
|
||||||
|
|
||||||
#[error("invalid message type")]
|
#[error("invalid message type")]
|
||||||
InvalidMessageType(u8),
|
InvalidMessageType(u8),
|
||||||
|
|
||||||
|
#[error("peer id {0:?} already taken")]
|
||||||
|
PeerIdAlreadyTaken(PeerId),
|
||||||
|
|
||||||
|
#[error("session id {0:?} already taken")]
|
||||||
|
SessionIdAlreadyTaken(SessionId),
|
||||||
|
|
||||||
|
#[error("{0}")]
|
||||||
|
NotImplemented(&'static str),
|
||||||
|
|
||||||
|
#[error("{0}")]
|
||||||
|
ConfigError(String),
|
||||||
|
|
||||||
|
#[error("see last log messages")]
|
||||||
|
RuntimeError,
|
||||||
|
|
||||||
|
#[error("{0}")]
|
||||||
|
IoError(#[from] std::io::Error),
|
||||||
|
|
||||||
|
#[error("{0}")]
|
||||||
|
TomlDeserError(#[from] toml::de::Error),
|
||||||
|
|
||||||
|
#[error("{0}")]
|
||||||
|
TomlSerError(#[from] toml::ser::Error),
|
||||||
|
|
||||||
|
#[error("invalid session id {0:?} was used")]
|
||||||
|
InvalidSessionId(SessionId),
|
||||||
|
|
||||||
|
#[error("no session available")]
|
||||||
|
NoSession,
|
||||||
|
#[error("the peer {0:?} does not exist")]
|
||||||
|
NoSuchPeer(PeerPtr),
|
||||||
|
|
||||||
|
#[error("the peer id {0:?} does not exist")]
|
||||||
|
NoSuchPeerId(PeerId),
|
||||||
|
|
||||||
|
#[error("the session {0:?} does not exist")]
|
||||||
|
NoSuchSessionId(SessionId),
|
||||||
|
|
||||||
|
#[error("no current handshake with peer {0:?}")]
|
||||||
|
NoCurrentHs(PeerPtr),
|
||||||
|
// TODO implement Display for Peer/Session ptr?
|
||||||
|
#[error("message seal broken")]
|
||||||
|
SealBroken,
|
||||||
|
|
||||||
|
#[error("received empty message")]
|
||||||
|
EmptyMessage,
|
||||||
|
|
||||||
|
#[error("biscuit with invalid number")]
|
||||||
|
InvalidBiscuitNo,
|
||||||
|
|
||||||
|
#[error("got unexpected message")]
|
||||||
|
UnexpectedMessage {
|
||||||
|
session: SessionId,
|
||||||
|
expected: Option<HandshakeStateMachine>,
|
||||||
|
got: Option<HandshakeStateMachine>,
|
||||||
|
},
|
||||||
|
|
||||||
|
#[error("???")]
|
||||||
|
StaleNonce,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Rosenpass Result type
|
||||||
|
pub type Result<T> = core::result::Result<T, RosenpassError>;
|
||||||
|
|
||||||
impl RosenpassError {
|
impl RosenpassError {
|
||||||
/// Helper function to check a buffer size
|
/// Helper function to check a buffer size
|
||||||
fn check_buffer_size(required_size: usize, actual_size: usize) -> Result<(), Self> {
|
fn check_buffer_size(required_size: usize, actual_size: usize) -> Result<()> {
|
||||||
if required_size != actual_size {
|
if required_size != actual_size {
|
||||||
Err(Self::BufferSizeMismatch {
|
Err(Self::BufferSizeMismatch {
|
||||||
required_size,
|
required_size,
|
||||||
@@ -45,11 +116,11 @@ impl RosenpassError {
|
|||||||
/// Extension trait to attach function calls to foreign types.
|
/// Extension trait to attach function calls to foreign types.
|
||||||
trait RosenpassMaybeError {
|
trait RosenpassMaybeError {
|
||||||
/// Checks whether something is an error or not
|
/// Checks whether something is an error or not
|
||||||
fn to_rg_error(&self) -> Result<(), RosenpassError>;
|
fn to_rg_error(&self) -> Result<()>;
|
||||||
}
|
}
|
||||||
|
|
||||||
impl RosenpassMaybeError for oqs_sys::common::OQS_STATUS {
|
impl RosenpassMaybeError for oqs_sys::common::OQS_STATUS {
|
||||||
fn to_rg_error(&self) -> Result<(), RosenpassError> {
|
fn to_rg_error(&self) -> Result<()> {
|
||||||
use oqs_sys::common::OQS_STATUS;
|
use oqs_sys::common::OQS_STATUS;
|
||||||
match self {
|
match self {
|
||||||
OQS_STATUS::OQS_SUCCESS => Ok(()),
|
OQS_STATUS::OQS_SUCCESS => Ok(()),
|
||||||
|
|||||||
@@ -1,10 +1,8 @@
|
|||||||
//! Implementation of the tree-like structure used for the label derivation in [labeled_prf](crate::labeled_prf)
|
//! Implementation of the tree-like structure used for the label derivation in [labeled_prf](crate::labeled_prf)
|
||||||
use {
|
use crate::{
|
||||||
crate::{
|
coloring::Secret,
|
||||||
coloring::Secret,
|
sodium::{hmac, hmac_into, KEY_SIZE},
|
||||||
sodium::{hmac, hmac_into, KEY_SIZE},
|
Result,
|
||||||
},
|
|
||||||
anyhow::Result,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// TODO Use a proper Dec interface
|
// TODO Use a proper Dec interface
|
||||||
|
|||||||
173
src/protocol.rs
173
src/protocol.rs
@@ -66,6 +66,8 @@
|
|||||||
//! # }
|
//! # }
|
||||||
//! ```
|
//! ```
|
||||||
|
|
||||||
|
use log::{trace, warn};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
coloring::*,
|
coloring::*,
|
||||||
labeled_prf as lprf,
|
labeled_prf as lprf,
|
||||||
@@ -74,8 +76,8 @@ use crate::{
|
|||||||
prftree::{SecretPrfTree, SecretPrfTreeBranch},
|
prftree::{SecretPrfTree, SecretPrfTreeBranch},
|
||||||
sodium::*,
|
sodium::*,
|
||||||
util::*,
|
util::*,
|
||||||
|
Result, RosenpassError,
|
||||||
};
|
};
|
||||||
use anyhow::{bail, ensure, Context, Result};
|
|
||||||
use std::collections::hash_map::{
|
use std::collections::hash_map::{
|
||||||
Entry::{Occupied, Vacant},
|
Entry::{Occupied, Vacant},
|
||||||
HashMap,
|
HashMap,
|
||||||
@@ -485,10 +487,8 @@ impl CryptoServer {
|
|||||||
let peerid = peer.pidt()?;
|
let peerid = peer.pidt()?;
|
||||||
let peerno = self.peers.len();
|
let peerno = self.peers.len();
|
||||||
match self.index.entry(IndexKey::Peer(peerid)) {
|
match self.index.entry(IndexKey::Peer(peerid)) {
|
||||||
Occupied(_) => bail!(
|
// TODO improve type handling, use PeerPtr
|
||||||
"Cannot insert peer with id {:?}; peer with this id already registered.",
|
Occupied(_) => return Err(RosenpassError::PeerIdAlreadyTaken(peerid)),
|
||||||
peerid
|
|
||||||
),
|
|
||||||
Vacant(e) => e.insert(peerno),
|
Vacant(e) => e.insert(peerno),
|
||||||
};
|
};
|
||||||
self.peers.push(peer);
|
self.peers.push(peer);
|
||||||
@@ -500,7 +500,7 @@ impl CryptoServer {
|
|||||||
pub fn register_session(&mut self, id: SessionId, peer: PeerPtr) -> Result<()> {
|
pub fn register_session(&mut self, id: SessionId, peer: PeerPtr) -> Result<()> {
|
||||||
match self.index.entry(IndexKey::Sid(id)) {
|
match self.index.entry(IndexKey::Sid(id)) {
|
||||||
Occupied(p) if PeerPtr(*p.get()) == peer => {} // Already registered
|
Occupied(p) if PeerPtr(*p.get()) == peer => {} // Already registered
|
||||||
Occupied(_) => bail!("Cannot insert session with id {:?}; id is in use.", id),
|
Occupied(_) => return Err(RosenpassError::SessionIdAlreadyTaken(id)),
|
||||||
Vacant(e) => {
|
Vacant(e) => {
|
||||||
e.insert(peer.0);
|
e.insert(peer.0);
|
||||||
}
|
}
|
||||||
@@ -522,8 +522,11 @@ impl CryptoServer {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn find_peer(&self, id: PeerId) -> Option<PeerPtr> {
|
pub fn find_peer(&self, id: PeerId) -> Result<PeerPtr> {
|
||||||
self.index.get(&IndexKey::Peer(id)).map(|no| PeerPtr(*no))
|
self.index
|
||||||
|
.get(&IndexKey::Peer(id))
|
||||||
|
.map(|no| PeerPtr(*no))
|
||||||
|
.ok_or_else(|| RosenpassError::NoSuchPeerId(id))
|
||||||
}
|
}
|
||||||
|
|
||||||
// lookup_session in whitepaper
|
// lookup_session in whitepaper
|
||||||
@@ -781,17 +784,21 @@ impl CryptoServer {
|
|||||||
/// | t2 | `InitConf` | -> | |
|
/// | t2 | `InitConf` | -> | |
|
||||||
/// | t3 | | <- | `EmptyData` |
|
/// | t3 | | <- | `EmptyData` |
|
||||||
pub fn handle_msg(&mut self, rx_buf: &[u8], tx_buf: &mut [u8]) -> Result<HandleMsgResult> {
|
pub fn handle_msg(&mut self, rx_buf: &[u8], tx_buf: &mut [u8]) -> Result<HandleMsgResult> {
|
||||||
let seal_broken = "Message seal broken!";
|
|
||||||
// length of the response. We assume no response, so None for now
|
// length of the response. We assume no response, so None for now
|
||||||
let mut len = 0;
|
let mut len = 0;
|
||||||
let mut exchanged = false;
|
let mut exchanged = false;
|
||||||
|
|
||||||
ensure!(!rx_buf.is_empty(), "received empty message, ignoring it");
|
if rx_buf.is_empty() {
|
||||||
|
trace!("received empty message, ignoring it");
|
||||||
|
return Err(RosenpassError::EmptyMessage);
|
||||||
|
}
|
||||||
|
|
||||||
let peer = match rx_buf[0].try_into() {
|
let peer = match rx_buf[0].try_into() {
|
||||||
Ok(MsgType::InitHello) => {
|
Ok(MsgType::InitHello) => {
|
||||||
let msg_in = rx_buf.envelope::<InitHello<&[u8]>>()?;
|
let msg_in = rx_buf.envelope::<InitHello<&[u8]>>()?;
|
||||||
ensure!(msg_in.check_seal(self)?, seal_broken);
|
if msg_in.check_seal(self)? {
|
||||||
|
return Err(RosenpassError::SealBroken);
|
||||||
|
}
|
||||||
|
|
||||||
let mut msg_out = tx_buf.envelope::<RespHello<&mut [u8]>>()?;
|
let mut msg_out = tx_buf.envelope::<RespHello<&mut [u8]>>()?;
|
||||||
let peer = self.handle_init_hello(
|
let peer = self.handle_init_hello(
|
||||||
@@ -803,7 +810,9 @@ impl CryptoServer {
|
|||||||
}
|
}
|
||||||
Ok(MsgType::RespHello) => {
|
Ok(MsgType::RespHello) => {
|
||||||
let msg_in = rx_buf.envelope::<RespHello<&[u8]>>()?;
|
let msg_in = rx_buf.envelope::<RespHello<&[u8]>>()?;
|
||||||
ensure!(msg_in.check_seal(self)?, seal_broken);
|
if msg_in.check_seal(self)? {
|
||||||
|
return Err(RosenpassError::SealBroken);
|
||||||
|
}
|
||||||
|
|
||||||
let mut msg_out = tx_buf.envelope::<InitConf<&mut [u8]>>()?;
|
let mut msg_out = tx_buf.envelope::<InitConf<&mut [u8]>>()?;
|
||||||
let peer = self.handle_resp_hello(
|
let peer = self.handle_resp_hello(
|
||||||
@@ -818,7 +827,9 @@ impl CryptoServer {
|
|||||||
}
|
}
|
||||||
Ok(MsgType::InitConf) => {
|
Ok(MsgType::InitConf) => {
|
||||||
let msg_in = rx_buf.envelope::<InitConf<&[u8]>>()?;
|
let msg_in = rx_buf.envelope::<InitConf<&[u8]>>()?;
|
||||||
ensure!(msg_in.check_seal(self)?, seal_broken);
|
if msg_in.check_seal(self)? {
|
||||||
|
return Err(RosenpassError::SealBroken);
|
||||||
|
}
|
||||||
|
|
||||||
let mut msg_out = tx_buf.envelope::<EmptyData<&mut [u8]>>()?;
|
let mut msg_out = tx_buf.envelope::<EmptyData<&mut [u8]>>()?;
|
||||||
let peer = self.handle_init_conf(
|
let peer = self.handle_init_conf(
|
||||||
@@ -831,15 +842,23 @@ impl CryptoServer {
|
|||||||
}
|
}
|
||||||
Ok(MsgType::EmptyData) => {
|
Ok(MsgType::EmptyData) => {
|
||||||
let msg_in = rx_buf.envelope::<EmptyData<&[u8]>>()?;
|
let msg_in = rx_buf.envelope::<EmptyData<&[u8]>>()?;
|
||||||
ensure!(msg_in.check_seal(self)?, seal_broken);
|
if msg_in.check_seal(self)? {
|
||||||
|
return Err(RosenpassError::SealBroken);
|
||||||
|
}
|
||||||
|
|
||||||
self.handle_resp_conf(msg_in.payload().empty_data()?)?
|
self.handle_resp_conf(msg_in.payload().empty_data()?)?
|
||||||
}
|
}
|
||||||
Ok(MsgType::DataMsg) => bail!("DataMsg handling not implemented!"),
|
Ok(MsgType::DataMsg) => {
|
||||||
Ok(MsgType::CookieReply) => bail!("CookieReply handling not implemented!"),
|
return Err(RosenpassError::NotImplemented(
|
||||||
Err(_) => {
|
"DataMsg handling not implemented!",
|
||||||
bail!("CookieReply handling not implemented!")
|
))
|
||||||
}
|
}
|
||||||
|
Ok(MsgType::CookieReply) => {
|
||||||
|
return Err(RosenpassError::NotImplemented(
|
||||||
|
"CookieReply handling not implemented!",
|
||||||
|
))
|
||||||
|
}
|
||||||
|
Err(e) => return Err(e),
|
||||||
};
|
};
|
||||||
|
|
||||||
Ok(HandleMsgResult {
|
Ok(HandleMsgResult {
|
||||||
@@ -1118,10 +1137,10 @@ impl CryptoServer {
|
|||||||
|
|
||||||
impl IniHsPtr {
|
impl IniHsPtr {
|
||||||
pub fn store_msg_for_retransmission(&self, srv: &mut CryptoServer, msg: &[u8]) -> Result<()> {
|
pub fn store_msg_for_retransmission(&self, srv: &mut CryptoServer, msg: &[u8]) -> Result<()> {
|
||||||
let ih = self
|
let ih = self.get_mut(srv).as_mut().ok_or_else(|| {
|
||||||
.get_mut(srv)
|
warn!("No current handshake for peer {:?}", self.peer());
|
||||||
.as_mut()
|
RosenpassError::NoCurrentHs(self.peer())
|
||||||
.with_context(|| format!("No current handshake for peer {:?}", self.peer()))?;
|
})?;
|
||||||
cpy_min(msg, &mut *ih.tx_buf);
|
cpy_min(msg, &mut *ih.tx_buf);
|
||||||
ih.tx_count = 0;
|
ih.tx_count = 0;
|
||||||
ih.tx_len = msg.len();
|
ih.tx_len = msg.len();
|
||||||
@@ -1130,20 +1149,20 @@ impl IniHsPtr {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn apply_retransmission(&self, srv: &mut CryptoServer, tx_buf: &mut [u8]) -> Result<usize> {
|
pub fn apply_retransmission(&self, srv: &mut CryptoServer, tx_buf: &mut [u8]) -> Result<usize> {
|
||||||
let ih = self
|
let ih = self.get_mut(srv).as_mut().ok_or_else(|| {
|
||||||
.get_mut(srv)
|
warn!("No current handshake for peer {:?}", self.peer());
|
||||||
.as_mut()
|
RosenpassError::NoCurrentHs(self.peer())
|
||||||
.with_context(|| format!("No current handshake for peer {:?}", self.peer()))?;
|
})?;
|
||||||
cpy_min(&ih.tx_buf[..ih.tx_len], tx_buf);
|
cpy_min(&ih.tx_buf[..ih.tx_len], tx_buf);
|
||||||
Ok(ih.tx_len)
|
Ok(ih.tx_len)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn register_retransmission(&self, srv: &mut CryptoServer) -> Result<()> {
|
pub fn register_retransmission(&self, srv: &mut CryptoServer) -> Result<()> {
|
||||||
let tb = srv.timebase.clone();
|
let tb = srv.timebase.clone();
|
||||||
let ih = self
|
let ih = self.get_mut(srv).as_mut().ok_or_else(|| {
|
||||||
.get_mut(srv)
|
warn!("No current handshake for peer {:?}", self.peer());
|
||||||
.as_mut()
|
RosenpassError::NoCurrentHs(self.peer())
|
||||||
.with_context(|| format!("No current handshake for peer {:?}", self.peer()))?;
|
})?;
|
||||||
// Base delay, exponential increase, ±50% jitter
|
// Base delay, exponential increase, ±50% jitter
|
||||||
ih.tx_retry_at = tb.now()
|
ih.tx_retry_at = tb.now()
|
||||||
+ RETRANSMIT_DELAY_BEGIN
|
+ RETRANSMIT_DELAY_BEGIN
|
||||||
@@ -1347,18 +1366,16 @@ impl HandshakeState {
|
|||||||
hs.mix(biscuit_ct)?;
|
hs.mix(biscuit_ct)?;
|
||||||
|
|
||||||
// Look up the associated peer
|
// Look up the associated peer
|
||||||
let peer = srv
|
let peer = srv.find_peer(pid)?;
|
||||||
.find_peer(pid) // TODO: FindPeer should return a Result<()>
|
|
||||||
.with_context(|| format!("Could not decode biscuit for peer {pid:?}: No such peer."))?;
|
|
||||||
|
|
||||||
// Defense against replay attacks; implementations may accept
|
// Defense against replay attacks; implementations may accept
|
||||||
// the most recent biscuit no again (bn = peer.bn_{prev}) which
|
// the most recent biscuit no again (bn = peer.bn_{prev}) which
|
||||||
// indicates retransmission
|
// indicates retransmission
|
||||||
// TODO: Handle retransmissions without involving the crypto code
|
// TODO: Handle retransmissions without involving the crypto code
|
||||||
ensure!(
|
if sodium_bigint_cmp(biscuit.biscuit_no(), &*peer.get(srv).biscuit_used) >= 0 {
|
||||||
sodium_bigint_cmp(biscuit.biscuit_no(), &*peer.get(srv).biscuit_used) >= 0,
|
warn!("Rejecting biscuit: Outdated biscuit number");
|
||||||
"Rejecting biscuit: Outdated biscuit number"
|
return Err(RosenpassError::InvalidBiscuitNo);
|
||||||
);
|
}
|
||||||
|
|
||||||
Ok((peer, no, hs))
|
Ok((peer, no, hs))
|
||||||
}
|
}
|
||||||
@@ -1392,11 +1409,10 @@ impl CryptoServer {
|
|||||||
///
|
///
|
||||||
/// Fail if no session is available with the peer
|
/// Fail if no session is available with the peer
|
||||||
pub fn osk(&self, peer: PeerPtr) -> Result<SymKey> {
|
pub fn osk(&self, peer: PeerPtr) -> Result<SymKey> {
|
||||||
let session = peer
|
let session = peer.session().get(self).as_ref().ok_or_else(|| {
|
||||||
.session()
|
warn!("No current session for peer {peer:?}");
|
||||||
.get(self)
|
RosenpassError::NoSuchPeer(peer)
|
||||||
.as_ref()
|
})?;
|
||||||
.with_context(|| format!("No current session for peer {:?}", peer))?;
|
|
||||||
Ok(session.ck.mix(&lprf::osk()?)?.into_secret())
|
Ok(session.ck.mix(&lprf::osk()?)?.into_secret())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1476,8 +1492,7 @@ impl CryptoServer {
|
|||||||
let peer = {
|
let peer = {
|
||||||
let mut peerid = PeerId::zero();
|
let mut peerid = PeerId::zero();
|
||||||
core.decrypt_and_mix(&mut *peerid, ih.pidic())?;
|
core.decrypt_and_mix(&mut *peerid, ih.pidic())?;
|
||||||
self.find_peer(peerid)
|
self.find_peer(peerid)?
|
||||||
.with_context(|| format!("No such peer {peerid:?}."))?
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// IHR7
|
// IHR7
|
||||||
@@ -1519,13 +1534,12 @@ impl CryptoServer {
|
|||||||
mut ic: InitConf<&mut [u8]>,
|
mut ic: InitConf<&mut [u8]>,
|
||||||
) -> Result<PeerPtr> {
|
) -> Result<PeerPtr> {
|
||||||
// RHI2
|
// RHI2
|
||||||
|
let sid = SessionId::from_slice(rh.sidi());
|
||||||
let peer = self
|
let peer = self
|
||||||
.lookup_handshake(SessionId::from_slice(rh.sidi()))
|
.lookup_handshake(sid)
|
||||||
.with_context(|| {
|
.ok_or_else(|| {
|
||||||
format!(
|
warn!("Got RespHello packet for non-existent session {sid:?}");
|
||||||
"Got RespHello packet for non-existent session {:?}",
|
RosenpassError::NoSuchSessionId(sid)
|
||||||
rh.sidi()
|
|
||||||
)
|
|
||||||
})?
|
})?
|
||||||
.peer();
|
.peer();
|
||||||
|
|
||||||
@@ -1546,13 +1560,14 @@ impl CryptoServer {
|
|||||||
let exp = hs!().next;
|
let exp = hs!().next;
|
||||||
let got = HandshakeStateMachine::RespHello;
|
let got = HandshakeStateMachine::RespHello;
|
||||||
|
|
||||||
ensure!(
|
if exp != got {
|
||||||
exp == got,
|
warn!("Unexpected package in session {sid:?}. Expected {exp:?}, got {got:?}.",);
|
||||||
"Unexpected package in session {:?}. Expected {:?}, got {:?}.",
|
return Err(RosenpassError::UnexpectedMessage {
|
||||||
SessionId::from_slice(rh.sidi()),
|
session: sid,
|
||||||
exp,
|
expected: Some(exp),
|
||||||
got
|
got: Some(got),
|
||||||
);
|
});
|
||||||
|
}
|
||||||
|
|
||||||
let mut core = hs!().core.clone();
|
let mut core = hs!().core.clone();
|
||||||
core.sidr.copy_from_slice(rh.sidr());
|
core.sidr.copy_from_slice(rh.sidr());
|
||||||
@@ -1669,11 +1684,10 @@ impl CryptoServer {
|
|||||||
// instead of a generic PeerPtr::send(&Server, Option<&[u8]>) -> Either<EmptyData, Data>
|
// instead of a generic PeerPtr::send(&Server, Option<&[u8]>) -> Either<EmptyData, Data>
|
||||||
// because data transmission is a stub currently. This software is supposed to be used
|
// because data transmission is a stub currently. This software is supposed to be used
|
||||||
// as a key exchange service feeding a PSK into some classical (i.e. non post quantum)
|
// as a key exchange service feeding a PSK into some classical (i.e. non post quantum)
|
||||||
let ses = peer
|
let ses = peer.session().get_mut(self).as_mut().ok_or_else(|| {
|
||||||
.session()
|
warn!("Cannot send acknowledgement. No session.");
|
||||||
.get_mut(self)
|
RosenpassError::NoSession
|
||||||
.as_mut()
|
})?;
|
||||||
.context("Cannot send acknowledgement. No session.")?;
|
|
||||||
rc.sid_mut().copy_from_slice(&ses.sidt.value);
|
rc.sid_mut().copy_from_slice(&ses.sidt.value);
|
||||||
rc.ctr_mut().copy_from_slice(&ses.txnm.to_le_bytes());
|
rc.ctr_mut().copy_from_slice(&ses.txnm.to_le_bytes());
|
||||||
ses.txnm += 1; // Increment nonce before encryption, just in case an error is raised
|
ses.txnm += 1; // Increment nonce before encryption, just in case an error is raised
|
||||||
@@ -1687,30 +1701,39 @@ impl CryptoServer {
|
|||||||
|
|
||||||
pub fn handle_resp_conf(&mut self, rc: EmptyData<&[u8]>) -> Result<PeerPtr> {
|
pub fn handle_resp_conf(&mut self, rc: EmptyData<&[u8]>) -> Result<PeerPtr> {
|
||||||
let sid = SessionId::from_slice(rc.sid());
|
let sid = SessionId::from_slice(rc.sid());
|
||||||
let hs = self
|
let hs = self.lookup_handshake(sid).ok_or_else(|| {
|
||||||
.lookup_handshake(sid)
|
warn!("Got RespConf packet for non-existent session {sid:?}");
|
||||||
.with_context(|| format!("Got RespConf packet for non-existent session {sid:?}"))?;
|
RosenpassError::InvalidSessionId(sid)
|
||||||
|
})?;
|
||||||
let ses = hs.peer().session();
|
let ses = hs.peer().session();
|
||||||
|
|
||||||
let exp = hs.get(self).as_ref().map(|h| h.next);
|
let exp = hs.get(self).as_ref().map(|h| h.next);
|
||||||
let got = Some(HandshakeStateMachine::RespConf);
|
let got = Some(HandshakeStateMachine::RespConf);
|
||||||
ensure!(
|
|
||||||
exp == got,
|
if exp != got {
|
||||||
"Unexpected package in session {:?}. Expected {:?}, got {:?}.",
|
warn!("Unexpected package in session {sid:?}. Expected {exp:?}, got {got:?}.",);
|
||||||
sid,
|
return Err(RosenpassError::UnexpectedMessage {
|
||||||
exp,
|
session: sid,
|
||||||
got
|
expected: exp,
|
||||||
);
|
got,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
// Validate the message
|
// Validate the message
|
||||||
{
|
{
|
||||||
let s = ses.get_mut(self).as_mut().with_context(|| {
|
// TODO get rid of as_mut necessity
|
||||||
format!("Cannot validate EmptyData message. Missing encryption session for {sid:?}")
|
let s = ses.get_mut(self).as_mut().ok_or_else(|| {
|
||||||
|
warn!("Cannot validate EmptyData message. Missing encryption session for {sid:?}");
|
||||||
|
RosenpassError::NoSuchSessionId(sid)
|
||||||
})?;
|
})?;
|
||||||
// the unwrap can not fail, because the slice returned by ctr() is
|
// the unwrap can not fail, because the slice returned by ctr() is
|
||||||
// guaranteed to have the correct size
|
// guaranteed to have the correct size
|
||||||
let n = u64::from_le_bytes(rc.ctr().try_into().unwrap());
|
let n = u64::from_le_bytes(rc.ctr().try_into().unwrap());
|
||||||
ensure!(n >= s.txnt, "Stale nonce");
|
|
||||||
|
if n < s.txnt {
|
||||||
|
trace!("Stale nonce");
|
||||||
|
return Err(RosenpassError::StaleNonce);
|
||||||
|
}
|
||||||
s.txnt = n;
|
s.txnt = n;
|
||||||
aead_dec_into(
|
aead_dec_into(
|
||||||
// pt, k, n, ad, ct
|
// pt, k, n, ad, ct
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
//! Bindings and helpers for accessing libsodium functions
|
//! Bindings and helpers for accessing libsodium functions
|
||||||
|
|
||||||
use crate::util::*;
|
use crate::{util::*, Result, RosenpassError};
|
||||||
use anyhow::{ensure, Result};
|
|
||||||
use libsodium_sys as libsodium;
|
use libsodium_sys as libsodium;
|
||||||
use log::trace;
|
use log::trace;
|
||||||
use static_assertions::const_assert_eq;
|
use static_assertions::const_assert_eq;
|
||||||
@@ -26,9 +25,11 @@ const_assert_eq!(KEY_SIZE, libsodium::crypto_generichash_BYTES as usize);
|
|||||||
|
|
||||||
macro_rules! sodium_call {
|
macro_rules! sodium_call {
|
||||||
($name:ident, $($args:expr),*) => { attempt!({
|
($name:ident, $($args:expr),*) => { attempt!({
|
||||||
ensure!(unsafe{libsodium::$name($($args),*)} > -1,
|
if unsafe{libsodium::$name($($args),*)} > -1 {
|
||||||
"Error in libsodium's {}.", stringify!($name));
|
Ok(())
|
||||||
Ok(())
|
}else{
|
||||||
|
Err(RosenpassError::LibsodiumError(concat!("Error in libsodium's {}.", stringify!($name))))
|
||||||
|
}
|
||||||
})};
|
})};
|
||||||
($name:ident) => { sodium_call!($name, ) };
|
($name:ident) => { sodium_call!($name, ) };
|
||||||
}
|
}
|
||||||
@@ -251,7 +252,12 @@ pub fn mac16(key: &[u8], data: &[u8]) -> Result<[u8; 16]> {
|
|||||||
pub fn hmac_into(out: &mut [u8], key: &[u8], data: &[u8]) -> Result<()> {
|
pub fn hmac_into(out: &mut [u8], key: &[u8], data: &[u8]) -> Result<()> {
|
||||||
// Not bothering with padding; the implementation
|
// Not bothering with padding; the implementation
|
||||||
// uses appropriately sized keys.
|
// uses appropriately sized keys.
|
||||||
ensure!(key.len() == KEY_SIZE);
|
if key.len() != KEY_SIZE {
|
||||||
|
return Err(crate::RosenpassError::BufferSizeMismatch {
|
||||||
|
required_size: KEY_SIZE,
|
||||||
|
actual_size: key.len(),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
const IPAD: [u8; KEY_SIZE] = [0x36u8; KEY_SIZE];
|
const IPAD: [u8; KEY_SIZE] = [0x36u8; KEY_SIZE];
|
||||||
let mut temp_key = [0u8; KEY_SIZE];
|
let mut temp_key = [0u8; KEY_SIZE];
|
||||||
|
|||||||
29
src/util.rs
29
src/util.rs
@@ -1,9 +1,9 @@
|
|||||||
//! Helper functions and macros
|
//! Helper functions and macros
|
||||||
use anyhow::{ensure, Context, Result};
|
|
||||||
use base64::{
|
use base64::{
|
||||||
display::Base64Display as B64Display, read::DecoderReader as B64Reader,
|
display::Base64Display as B64Display, read::DecoderReader as B64Reader,
|
||||||
write::EncoderWriter as B64Writer,
|
write::EncoderWriter as B64Writer,
|
||||||
};
|
};
|
||||||
|
use log::error;
|
||||||
use std::{
|
use std::{
|
||||||
borrow::{Borrow, BorrowMut},
|
borrow::{Borrow, BorrowMut},
|
||||||
cmp::min,
|
cmp::min,
|
||||||
@@ -13,7 +13,10 @@ use std::{
|
|||||||
time::{Duration, Instant},
|
time::{Duration, Instant},
|
||||||
};
|
};
|
||||||
|
|
||||||
use crate::coloring::{Public, Secret};
|
use crate::{
|
||||||
|
coloring::{Public, Secret},
|
||||||
|
Result,
|
||||||
|
};
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn xor_into(a: &mut [u8], b: &[u8]) {
|
pub fn xor_into(a: &mut [u8], b: &[u8]) {
|
||||||
@@ -58,7 +61,7 @@ pub fn cpy_min<T: BorrowMut<[u8]> + ?Sized, F: Borrow<[u8]> + ?Sized>(src: &F, d
|
|||||||
#[macro_export]
|
#[macro_export]
|
||||||
macro_rules! attempt {
|
macro_rules! attempt {
|
||||||
($block:expr) => {
|
($block:expr) => {
|
||||||
(|| -> ::anyhow::Result<_> { $block })()
|
(|| -> crate::Result<_> { $block })()
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -150,8 +153,12 @@ impl<R: Read> ReadExactToEnd for R {
|
|||||||
fn read_exact_to_end(&mut self, buf: &mut [u8]) -> Result<()> {
|
fn read_exact_to_end(&mut self, buf: &mut [u8]) -> Result<()> {
|
||||||
let mut dummy = [0u8; 8];
|
let mut dummy = [0u8; 8];
|
||||||
self.read_exact(buf)?;
|
self.read_exact(buf)?;
|
||||||
ensure!(self.read(&mut dummy)? == 0, "File too long!");
|
if self.read(&mut dummy)? != 0 {
|
||||||
Ok(())
|
error!("File too long!");
|
||||||
|
Err(crate::RosenpassError::RuntimeError)
|
||||||
|
} else {
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -185,9 +192,10 @@ impl<const N: usize> LoadValue for Secret<N> {
|
|||||||
fn load<P: AsRef<Path>>(path: P) -> Result<Self> {
|
fn load<P: AsRef<Path>>(path: P) -> Result<Self> {
|
||||||
let mut v = Self::random();
|
let mut v = Self::random();
|
||||||
let p = path.as_ref();
|
let p = path.as_ref();
|
||||||
fopen_r(p)?
|
fopen_r(p)?.read_exact_to_end(v.secret_mut()).map_err(|e| {
|
||||||
.read_exact_to_end(v.secret_mut())
|
error!("Could not load file {p:?}");
|
||||||
.with_context(|| format!("Could not load file {p:?}"))?;
|
e
|
||||||
|
})?;
|
||||||
Ok(v)
|
Ok(v)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -205,7 +213,10 @@ impl<const N: usize> LoadValueB64 for Secret<N> {
|
|||||||
// not worth it right now.
|
// not worth it right now.
|
||||||
b64_reader(&mut fopen_r(p)?)
|
b64_reader(&mut fopen_r(p)?)
|
||||||
.read_exact(v.secret_mut())
|
.read_exact(v.secret_mut())
|
||||||
.with_context(|| format!("Could not load base64 file {p:?}"))?;
|
.map_err(|e| {
|
||||||
|
error!("Could not load base64 file {p:?}");
|
||||||
|
e
|
||||||
|
})?;
|
||||||
Ok(v)
|
Ok(v)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user