Compare commits

...

432 Commits

Author SHA1 Message Date
wucke13
00b1020f0a refactor(flake.nix): externalize pkgs, add overlay
This splits the complexity of the `flake.nix` into multiple files. At
cross-compiled and static builds at the benefit of simpler nix
expressions and generally better cross compilation compatibility.
the same time, naersk is removed; causing much slower builds for cross-
compiled packages.

This partially addresses the points mentioned in #412.
2024-10-08 14:47:18 +02:00
dependabot[bot]
a5208795f6 build(deps): bump futures from 0.3.30 to 0.3.31
Bumps [futures](https://github.com/rust-lang/futures-rs) from 0.3.30 to 0.3.31.
- [Release notes](https://github.com/rust-lang/futures-rs/releases)
- [Changelog](https://github.com/rust-lang/futures-rs/blob/master/CHANGELOG.md)
- [Commits](https://github.com/rust-lang/futures-rs/compare/0.3.30...0.3.31)

---
updated-dependencies:
- dependency-name: futures
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-10-08 14:27:46 +02:00
Karolin Varner
0959148305 ci: add concurrency option to skip in progress
Merge pull request #432 from aparcar/con
2024-10-03 16:48:02 +02:00
Paul Spooren
f2bc3a8b64 ci: Rename regression workflow to "Regression"
No magic here, this is likely a copy&paste error. Problem is that one
workflow being called "QC" (regressions.yml) cancels out the other "QC"
(qc.yaml).

Signed-off-by: Paul Spooren <mail@aparcar.org>
2024-10-03 16:47:49 +02:00
Paul Spooren
06529df2c0 ci: add concurrency option to skip in progress
Instead of running outdated CI jobs, skip them automatically.

Signed-off-by: Paul Spooren <mail@aparcar.org>
2024-10-03 16:47:49 +02:00
Karolin Varner
128c77f77a ci: Skip Nix build of aarch64 since it takes forever
Merge pull request #433 from aparcar/no-arm-ci
2024-10-03 16:47:09 +02:00
Karolin Varner
501cc9bb05 Merge branch 'main' into no-arm-ci 2024-10-03 16:46:36 +02:00
dependabot[bot]
9ad5277a90 build(deps): bump clap from 4.5.18 to 4.5.19
Bumps [clap](https://github.com/clap-rs/clap) from 4.5.18 to 4.5.19.
- [Release notes](https://github.com/clap-rs/clap/releases)
- [Changelog](https://github.com/clap-rs/clap/blob/master/CHANGELOG.md)
- [Commits](https://github.com/clap-rs/clap/compare/clap_complete-v4.5.18...clap_complete-v4.5.19)

---
updated-dependencies:
- dependency-name: clap
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-10-02 18:45:26 +02:00
Paul Spooren
0cbcaeaf98 ci: Skip Nix build of aarch64 since it takes forever
More than 6 hours aka failing the CI. Drop it for now and hope to have
it enabled later again.

Signed-off-by: Paul Spooren <mail@aparcar.org>
2024-10-01 14:18:50 +02:00
Paul Spooren
687ef3f6f8 docs: Correct protocol retransmission unit/vars
Those are seconds not ms, also it's BEGIN not BEG.

While over there, drop the unused variable `RETRANSMIT_ABORT` which was
never used anywhere in the code and drop an outdated TODO comment.

Signed-off-by: Paul Spooren <mail@aparcar.org>
2024-10-01 14:08:44 +02:00
Paul Spooren
b0706354d3 chore: Format all Cargo.toml files
Signed-off-by: Paul Spooren <mail@aparcar.org>
2024-10-01 11:22:45 +01:00
dependabot[bot]
c1e86daec8 build(deps): bump libc from 0.2.158 to 0.2.159 (#429)
Bumps [libc](https://github.com/rust-lang/libc) from 0.2.158 to 0.2.159.
- [Release notes](https://github.com/rust-lang/libc/releases)
- [Changelog](https://github.com/rust-lang/libc/blob/0.2.159/CHANGELOG.md)
- [Commits](https://github.com/rust-lang/libc/compare/0.2.158...0.2.159)

---
updated-dependencies:
- dependency-name: libc
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-09-25 20:02:31 +02:00
dependabot[bot]
18a286e688 build(deps): bump thiserror from 1.0.63 to 1.0.64 (#428)
Bumps [thiserror](https://github.com/dtolnay/thiserror) from 1.0.63 to 1.0.64.
- [Release notes](https://github.com/dtolnay/thiserror/releases)
- [Commits](https://github.com/dtolnay/thiserror/compare/1.0.63...1.0.64)

---
updated-dependencies:
- dependency-name: thiserror
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-09-24 17:28:42 +02:00
dependabot[bot]
cb92313391 build(deps): bump clap from 4.5.17 to 4.5.18 (#427)
Bumps [clap](https://github.com/clap-rs/clap) from 4.5.17 to 4.5.18.
- [Release notes](https://github.com/clap-rs/clap/releases)
- [Changelog](https://github.com/clap-rs/clap/blob/master/CHANGELOG.md)
- [Commits](https://github.com/clap-rs/clap/compare/clap_complete-v4.5.17...clap_complete-v4.5.18)

---
updated-dependencies:
- dependency-name: clap
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-09-21 09:26:54 +02:00
dependabot[bot]
5cd30b4c13 build(deps): bump anyhow from 1.0.88 to 1.0.89 (#425)
Bumps [anyhow](https://github.com/dtolnay/anyhow) from 1.0.88 to 1.0.89.
- [Release notes](https://github.com/dtolnay/anyhow/releases)
- [Commits](https://github.com/dtolnay/anyhow/compare/1.0.88...1.0.89)

---
updated-dependencies:
- dependency-name: anyhow
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-09-17 17:41:27 +02:00
dependabot[bot]
76d8d38744 build(deps): bump rustix from 0.38.36 to 0.38.37
Bumps [rustix](https://github.com/bytecodealliance/rustix) from 0.38.36 to 0.38.37.
- [Release notes](https://github.com/bytecodealliance/rustix/releases)
- [Changelog](https://github.com/bytecodealliance/rustix/blob/main/CHANGELOG.md)
- [Commits](https://github.com/bytecodealliance/rustix/compare/v0.38.36...v0.38.37)

---
updated-dependencies:
- dependency-name: rustix
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-09-12 19:01:42 +02:00
dependabot[bot]
f63f0bbc2e build(deps): bump anyhow from 1.0.87 to 1.0.88
Bumps [anyhow](https://github.com/dtolnay/anyhow) from 1.0.87 to 1.0.88.
- [Release notes](https://github.com/dtolnay/anyhow/releases)
- [Commits](https://github.com/dtolnay/anyhow/compare/1.0.87...1.0.88)

---
updated-dependencies:
- dependency-name: anyhow
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-09-12 19:01:31 +02:00
Karolin Varner
4a449e6502 chore: drop copy & paste doc error in protocol.rs
Merge pull request #422 from aparcar/cos1
2024-09-10 18:02:49 +02:00
Karolin Varner
1e6d2df004 Merge branch 'main' into cos1 2024-09-10 18:02:25 +02:00
Paul Spooren
3fa9aadda2 chore: drop copy & paste doc error in protocol.rs
There seem to be a paste typo in the docs, drop it to lower confusion.

Signed-off-by: Paul Spooren <mail@aparcar.org>
2024-09-10 12:39:57 +02:00
dependabot[bot]
0c79a4ce95 build(deps): bump serde from 1.0.209 to 1.0.210 (#420)
Bumps [serde](https://github.com/serde-rs/serde) from 1.0.209 to 1.0.210.
- [Release notes](https://github.com/serde-rs/serde/releases)
- [Commits](https://github.com/serde-rs/serde/compare/v1.0.209...v1.0.210)

---
updated-dependencies:
- dependency-name: serde
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-09-09 16:22:00 +02:00
dependabot[bot]
036960b5b1 build(deps): bump anyhow from 1.0.86 to 1.0.87 (#421)
Bumps [anyhow](https://github.com/dtolnay/anyhow) from 1.0.86 to 1.0.87.
- [Release notes](https://github.com/dtolnay/anyhow/releases)
- [Commits](https://github.com/dtolnay/anyhow/compare/1.0.86...1.0.87)

---
updated-dependencies:
- dependency-name: anyhow
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-09-09 15:01:01 +02:00
dependabot[bot]
e7258849cb build(deps): bump rustix from 0.38.35 to 0.38.36 (#419)
Bumps [rustix](https://github.com/bytecodealliance/rustix) from 0.38.35 to 0.38.36.
- [Release notes](https://github.com/bytecodealliance/rustix/releases)
- [Commits](https://github.com/bytecodealliance/rustix/compare/v0.38.35...v0.38.36)

---
updated-dependencies:
- dependency-name: rustix
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-09-06 09:53:51 +02:00
dependabot[bot]
8c88f68990 build(deps): bump clap from 4.5.16 to 4.5.17
Bumps [clap](https://github.com/clap-rs/clap) from 4.5.16 to 4.5.17.
- [Release notes](https://github.com/clap-rs/clap/releases)
- [Changelog](https://github.com/clap-rs/clap/blob/master/CHANGELOG.md)
- [Commits](https://github.com/clap-rs/clap/compare/clap_complete-v4.5.16...clap_complete-v4.5.17)

---
updated-dependencies:
- dependency-name: clap
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-09-05 10:24:56 +02:00
dependabot[bot]
cf20536576 build(deps): bump tokio from 1.39.3 to 1.40.0
Bumps [tokio](https://github.com/tokio-rs/tokio) from 1.39.3 to 1.40.0.
- [Release notes](https://github.com/tokio-rs/tokio/releases)
- [Commits](https://github.com/tokio-rs/tokio/compare/tokio-1.39.3...tokio-1.40.0)

---
updated-dependencies:
- dependency-name: tokio
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-08-31 11:30:00 +02:00
dependabot[bot]
72e18e3ec2 build(deps): bump derive_builder from 0.20.0 to 0.20.1
Bumps [derive_builder](https://github.com/colin-kiegel/rust-derive-builder) from 0.20.0 to 0.20.1.
- [Release notes](https://github.com/colin-kiegel/rust-derive-builder/releases)
- [Commits](https://github.com/colin-kiegel/rust-derive-builder/compare/v0.20.0...v0.20.1)

---
updated-dependencies:
- dependency-name: derive_builder
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-08-30 08:56:28 +02:00
dependabot[bot]
6040156a0e build(deps): bump rustix from 0.38.34 to 0.38.35 (#414)
Bumps [rustix](https://github.com/bytecodealliance/rustix) from 0.38.34 to 0.38.35.
- [Release notes](https://github.com/bytecodealliance/rustix/releases)
- [Commits](https://github.com/bytecodealliance/rustix/compare/v0.38.34...v0.38.35)

---
updated-dependencies:
- dependency-name: rustix
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-08-28 20:39:53 +02:00
dependabot[bot]
d3b318b413 build(deps): bump stacker from 0.1.16 to 0.1.17 (#415)
Bumps [stacker](https://github.com/rust-lang/stacker) from 0.1.16 to 0.1.17.
- [Commits](https://github.com/rust-lang/stacker/compare/stacker-0.1.16...stacker-0.1.17)

---
updated-dependencies:
- dependency-name: stacker
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-08-28 20:39:25 +02:00
dependabot[bot]
3a49345138 build(deps): bump serde from 1.0.208 to 1.0.209 (#413)
Bumps [serde](https://github.com/serde-rs/serde) from 1.0.208 to 1.0.209.
- [Release notes](https://github.com/serde-rs/serde/releases)
- [Commits](https://github.com/serde-rs/serde/compare/v1.0.208...v1.0.209)

---
updated-dependencies:
- dependency-name: serde
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-08-27 20:02:59 +02:00
dependabot[bot]
4ec7813259 build(deps): bump stacker from 0.1.15 to 0.1.16
Bumps [stacker](https://github.com/rust-lang/stacker) from 0.1.15 to 0.1.16.
- [Commits](https://github.com/rust-lang/stacker/compare/stacker-0.1.15...stacker-0.1.16)

---
updated-dependencies:
- dependency-name: stacker
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-08-22 16:54:13 +02:00
dependabot[bot]
db31da14d3 build(deps): bump postcard from 1.0.9 to 1.0.10
Bumps [postcard](https://github.com/jamesmunns/postcard) from 1.0.9 to 1.0.10.
- [Release notes](https://github.com/jamesmunns/postcard/releases)
- [Changelog](https://github.com/jamesmunns/postcard/blob/main/CHANGELOG.md)
- [Commits](https://github.com/jamesmunns/postcard/compare/v1.0.9...v1.0.10)

---
updated-dependencies:
- dependency-name: postcard
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-08-22 16:54:00 +02:00
Karolin Varner
4c20efc8a8 Merge: fix(API): Tests failing on mac
Merge pull request #409 from rosenpass/dev/karo/macos-fix
2024-08-21 13:46:53 +02:00
Karolin Varner
c81d484294 fix(API): Tests failing on mac 2024-08-21 12:48:45 +02:00
dependabot[bot]
cc578169d6 build(deps): bump postcard from 1.0.8 to 1.0.9 (#408)
Bumps [postcard](https://github.com/jamesmunns/postcard) from 1.0.8 to 1.0.9.
- [Release notes](https://github.com/jamesmunns/postcard/releases)
- [Changelog](https://github.com/jamesmunns/postcard/blob/main/CHANGELOG.md)
- [Commits](https://github.com/jamesmunns/postcard/compare/v1.0.8...v1.0.9)

---
updated-dependencies:
- dependency-name: postcard
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-08-21 08:12:56 +02:00
dependabot[bot]
91527702f1 build(deps): bump tokio from 1.39.2 to 1.39.3 (#407)
Bumps [tokio](https://github.com/tokio-rs/tokio) from 1.39.2 to 1.39.3.
- [Release notes](https://github.com/tokio-rs/tokio/releases)
- [Commits](https://github.com/tokio-rs/tokio/compare/tokio-1.39.2...tokio-1.39.3)

---
updated-dependencies:
- dependency-name: tokio
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-08-21 08:12:39 +02:00
dependabot[bot]
0179f1c673 build(deps): bump libc from 0.2.156 to 0.2.158 (#406)
Bumps [libc](https://github.com/rust-lang/libc) from 0.2.156 to 0.2.158.
- [Release notes](https://github.com/rust-lang/libc/releases)
- [Changelog](https://github.com/rust-lang/libc/blob/0.2.158/CHANGELOG.md)
- [Commits](https://github.com/rust-lang/libc/compare/0.2.156...0.2.158)

---
updated-dependencies:
- dependency-name: libc
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-08-21 08:12:05 +02:00
Karolin Varner
2238919657 Merge: fd/time: add tests, docs, cleanups
Merge pull request #405 from aparcar/fd-tests-cleanup
2024-08-19 17:52:42 +02:00
Paul Spooren
d913e19883 test: add tests for controlflow
While at it, fix the label handling and fix a typo in continue_if, where
a `break` falsely replaced a `continue`

Signed-off-by: Paul Spooren <mail@aparcar.org>
2024-08-19 17:24:38 +02:00
Paul Spooren
1555d0897b feat(ord): drop obsolete RTX_BUFFER_SIZE and usize_max
The RTX_BUFFER_SIZE function is nowhere used in the code and when
dropping it, usize_max (const version of max()) becomes obsolete, too.

Signed-off-by: Paul Spooren <mail@aparcar.org>
2024-08-19 17:24:37 +02:00
Paul Spooren
abdbf8f3da feat(util/time): cleanup, document and add tests
Drop the unused `dur` function, it's nowhere found in the code.

Document both Timebase and Timebase::now()

Add tests

Signed-off-by: Paul Spooren <mail@aparcar.org>
2024-08-19 17:24:16 +02:00
Paul Spooren
9f78531979 tests: cleanup fd.rs tests
Trigger the internal assert of owned.rs instead of writing our own. To
correctly test it use `should_panic` macro.

Signed-off-by: Paul Spooren <mail@aparcar.org>
2024-08-19 17:24:16 +02:00
Karolin Varner
624d8d2f44 Merge: API: Close connections after errors & use mio::Token based polling
Merge pull request #404 from rosenpass/dev/karo/api_remove_connection
2024-08-19 15:03:46 +02:00
Karolin Varner
9bbf9433e6 fix(API): Be polite and kill child processes in api integration tests 2024-08-19 00:31:01 +02:00
Karolin Varner
77760d71df feat(API): Use mio::Token based polling
Avoid polling every single IO source to collect events,
poll those specific IO sources mio tells us about.
2024-08-19 00:31:01 +02:00
Karolin Varner
53e560191f feat(API): Close API connections after error 2024-08-19 00:31:01 +02:00
Karolin Varner
93cd266c68 Merge API Endpoint: AddPskBroker
Merge pull request #403 from rosenpass/dev/karo/api-add-psk-broker
2024-08-17 22:25:21 +02:00
Karolin Varner
594f894206 feat(API): AddPskBroker endpoint 2024-08-17 15:30:10 +02:00
Karolin Varner
a831e01a5c chore: Utilities to check for unix domain stream sockets 2024-08-17 15:30:10 +02:00
dependabot[bot]
0884641d64 build(deps): bump libc from 0.2.155 to 0.2.156
Bumps [libc](https://github.com/rust-lang/libc) from 0.2.155 to 0.2.156.
- [Release notes](https://github.com/rust-lang/libc/releases)
- [Changelog](https://github.com/rust-lang/libc/blob/0.2.156/CHANGELOG.md)
- [Commits](https://github.com/rust-lang/libc/compare/0.2.155...0.2.156)

---
updated-dependencies:
- dependency-name: libc
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-08-17 10:54:06 +02:00
dependabot[bot]
ae85d0ed2b build(deps): bump clap from 4.5.15 to 4.5.16
Bumps [clap](https://github.com/clap-rs/clap) from 4.5.15 to 4.5.16.
- [Release notes](https://github.com/clap-rs/clap/releases)
- [Changelog](https://github.com/clap-rs/clap/blob/master/CHANGELOG.md)
- [Commits](https://github.com/clap-rs/clap/compare/clap_complete-v4.5.15...clap_complete-v4.5.16)

---
updated-dependencies:
- dependency-name: clap
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-08-16 17:28:51 +02:00
Karolin Varner
163f66f20e Merge – API Feature: Adding listen sockets
Merge pull request #395 from rosenpass/dev/karo/api-add-listen-socket
2024-08-16 17:16:44 +02:00
Paul Spooren
3caff91515 rosenpass: fallback for empty api section in config
The [api] section is newly added and causes existing installation to
break since they lack the configuration options. Instead, use a serde
default function.

Signed-off-by: Paul Spooren <mail@aparcar.org>
Co-authored-by: Karolin Varner <karo@cupdev.net>
2024-08-16 14:37:42 +02:00
Karolin Varner
24eebe29a1 feat(API): AddListenSocket endpoint 2024-08-16 14:37:42 +02:00
Karolin Varner
1d2fa7d038 feat(api): API Feature – Add server keys via API
Merge pull request #392 from rosenpass/dev/karo/api-supply-server-keys
2024-08-16 11:22:46 +02:00
Karolin Varner
edf1e774c1 feat(API): SupplyKeypair endpoint 2024-08-16 11:13:34 +02:00
Karolin Varner
7a31b57227 chore(API): Infrastructure to use endpoints with fd. passing 2024-08-16 08:39:27 +02:00
Karolin Varner
d5a8c85abe chore(API): Specifying a keypair should be opt. at startup
…so we can specify it later using the API.
2024-08-16 08:34:07 +02:00
Karolin Varner
48f7ff93e3 chore(API, AppServer): Deal with CryptoServer being uninit.
Before this, we would just raise an error.
2024-08-16 08:34:07 +02:00
Karolin Varner
5f6c36e773 chore(AppServer): Decouple AppServer from CryptoServer::timebase 2024-08-16 08:34:07 +02:00
Karolin Varner
7b3b7612cf chore(api): API should have access to AppServer
The borrow checker does not approve, hence there are many shenanigans
with extension traits.
2024-08-16 08:34:07 +02:00
Karolin Varner
c1704b1464 fix(API): Wrong response size set 2024-08-16 08:34:07 +02:00
dependabot[bot]
2785aaf783 build(deps): bump serde from 1.0.207 to 1.0.208
Bumps [serde](https://github.com/serde-rs/serde) from 1.0.207 to 1.0.208.
- [Release notes](https://github.com/serde-rs/serde/releases)
- [Commits](https://github.com/serde-rs/serde/compare/v1.0.207...v1.0.208)

---
updated-dependencies:
- dependency-name: serde
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-08-16 08:30:08 +02:00
Karolin Varner
15002a74cc Merge: Experimental PSK Broker Support
Merge pull request #376 from pqcfox/feat/netlink-broker-cli

Add broker support to Rosenpass using `MioBrokerClient` (backport of dev/broker-architecture)
2024-08-16 08:26:15 +02:00
Karolin Varner
0fe2d9825b fix: Remove ineffectual broker integration test 2024-08-16 00:35:46 +02:00
Karolin Varner
ab805dae75 fix: libc & rustix are making problems in CI for unknown reasons 2024-08-16 00:35:46 +02:00
Karolin Varner
08653c3338 chore: clippy 2024-08-16 00:35:46 +02:00
Karolin Varner
520c8c6eaa chore: Feature naming scheme fully applied
experimental_broker_api -> experiment_broker_api
2024-08-15 22:47:20 +02:00
Karolin Varner
258efe408c fix: PSK broker integration did not work
This commit resolves multiple issues with the PSK broker integration.

- The manual testing procedure never actually utilized the brokers
  due to the use of the outfile option, this led to issues with the
  broker being hidden.
- The manual testing procedure omitted checking whether a PSK was
  actually sent to WireGuard entirely. This was fixed by writing an
  entirely new manual integration testing shell-script that can serve
  as a blueprint for future integration tests.
- Many parts of the PSK broker code did not report (log) errors
  accurately; added error logging
- BrokerServer set message.payload.return_code to the msg_type value,
  this led to crashes
- The PSK broker commands all omitted to set the memfd policy, this led
  to immediate crashes once secrets where actually allocated
- The MioBrokerClient IO state machine was broken and the design was
  too obtuse to debug. The state machine returned the length prefix as
  a message instead of actually interpreting it as a state machine.
  Seems the code was integrated but never actually tested. This was
  fixed by rewriting the entire state machine code using the new
  LengthPrefixEncoder/Decoder facilities. A write-buffer that was not
  being flushed is now handled by flushing the buffer in blocking-io
  mode.
2024-08-15 22:47:20 +02:00
Karolin Varner
fd0f35b279 chore: gen-key subcommand should show canonical paths 2024-08-15 22:12:02 +02:00
Karolin Varner
8808ed5dbc fix: Quiet log level should be warn 2024-08-15 09:43:25 +02:00
Karolin Varner
6fc45cab53 chore: prettier 2024-08-15 08:55:13 +02:00
Katherine Watson
1f7196e473 doc: Add documentation for testing 2024-08-14 19:49:00 -07:00
Katherine Watson
c359b87d0c chore: Convert broker interface setup to use mio's UnixStream where possible 2024-08-14 19:03:45 -07:00
Katherine Watson
355b48169b chore: Make MiobrokerClient import conditional 2024-08-14 19:03:45 -07:00
Katherine Watson
274d245bed chore: Unify enable_wg_broker and enable_broker_api features 2024-08-14 19:03:45 -07:00
Katherine Watson
065b0fcc8a feat: Add enable_wg_broker feature using MioBrokerClient
doc: Add documentation for new methods and arguments

fix: Require new psk_broker_spawn flag to use broker without extra parameters, to make all-features cargo test pass

fix: Fix MioBrokerClient buffer size to allow room for length prefix

fix: Fix remaining issue with panic
2024-08-14 19:03:44 -07:00
dependabot[bot]
191fb10663 build(deps): bump mio from 1.0.1 to 1.0.2
Bumps [mio](https://github.com/tokio-rs/mio) from 1.0.1 to 1.0.2.
- [Release notes](https://github.com/tokio-rs/mio/releases)
- [Changelog](https://github.com/tokio-rs/mio/blob/master/CHANGELOG.md)
- [Commits](https://github.com/tokio-rs/mio/compare/v1.0.1...v1.0.2)

---
updated-dependencies:
- dependency-name: mio
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-08-14 09:28:27 +02:00
dependabot[bot]
3faa84117f build(deps): bump tokio from 1.39.1 to 1.39.2
Bumps [tokio](https://github.com/tokio-rs/tokio) from 1.39.1 to 1.39.2.
- [Release notes](https://github.com/tokio-rs/tokio/releases)
- [Commits](https://github.com/tokio-rs/tokio/compare/tokio-1.39.1...tokio-1.39.2)

---
updated-dependencies:
- dependency-name: tokio
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-08-13 13:14:15 +02:00
dependabot[bot]
fda75a0184 build(deps): bump serde from 1.0.204 to 1.0.207
Bumps [serde](https://github.com/serde-rs/serde) from 1.0.204 to 1.0.207.
- [Release notes](https://github.com/serde-rs/serde/releases)
- [Commits](https://github.com/serde-rs/serde/compare/v1.0.204...v1.0.207)

---
updated-dependencies:
- dependency-name: serde
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-08-13 13:14:03 +02:00
dependabot[bot]
96b1f6c0d3 build(deps): bump procspawn from 1.0.0 to 1.0.1 (#390)
Bumps [procspawn](https://github.com/mitsuhiko/procspawn) from 1.0.0 to 1.0.1.
- [Changelog](https://github.com/mitsuhiko/procspawn/blob/master/CHANGELOG.md)
- [Commits](https://github.com/mitsuhiko/procspawn/compare/1.0.0...1.0.1)

---
updated-dependencies:
- dependency-name: procspawn
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-08-13 08:15:57 +02:00
dependabot[bot]
fb73c68626 build(deps): bump tempfile from 3.10.1 to 3.11.0 (#387)
Bumps [tempfile](https://github.com/Stebalien/tempfile) from 3.10.1 to 3.11.0.
- [Changelog](https://github.com/Stebalien/tempfile/blob/master/CHANGELOG.md)
- [Commits](https://github.com/Stebalien/tempfile/compare/v3.10.1...v3.11.0)

---
updated-dependencies:
- dependency-name: tempfile
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-08-13 08:15:46 +02:00
dependabot[bot]
42b0e23695 build(deps): bump clap from 4.5.13 to 4.5.15 (#397)
Bumps [clap](https://github.com/clap-rs/clap) from 4.5.13 to 4.5.15.
- [Release notes](https://github.com/clap-rs/clap/releases)
- [Changelog](https://github.com/clap-rs/clap/blob/master/CHANGELOG.md)
- [Commits](https://github.com/clap-rs/clap/compare/clap_complete-v4.5.13...clap_complete-v4.5.15)

---
updated-dependencies:
- dependency-name: clap
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-08-13 08:13:06 +02:00
Karolin Varner
c58f832727 Merge pull request #391 from aparcar/pb
add test cases for util modules
2024-08-12 16:26:01 +02:00
Paul Spooren
7b6a9eebc1 ci: test full workspace with codecov
Previously only the default members were checked for coverage.

Signed-off-by: Paul Spooren <mail@aparcar.org>
2024-08-12 12:10:47 +02:00
Paul Spooren
4554dc4bb3 ci: drop codecov token
It's not needed to see generate results for pull requests.

Signed-off-by: Paul Spooren <mail@aparcar.org>
2024-08-12 11:44:33 +02:00
Paul Spooren
465c6beaab ci: switch to codecov action v4 branch
Instead of using a specific version, use branch v4 which stays API
compatible.

Signed-off-by: Paul Spooren <mail@aparcar.org>
2024-08-12 11:43:26 +02:00
Paul Spooren
1853e0a3c0 feat: add test case and check fd value
Signed-off-by: Paul Spooren <mail@aparcar.org>
2024-08-12 11:37:15 +02:00
Benjamin Lipp
245d4d1a0f feat: add tests for util file.rs
Co-authored-by: Paul Spooren <mail@aparcar.org>
2024-08-12 11:37:15 +02:00
Karolin Varner
d5d15cd9bc Merge Rosenpass API infrastructure
Pull request #388 from rosenpass/dev/karo/api
2024-08-08 22:02:04 +02:00
Katherine Watson
9fd3df67ed chore: Fix typos and add various comments 2024-08-07 23:11:13 -07:00
Karolin Varner
6d47169a5c feat: Set CLOEXEC flag on claimed fds and mask them
Masking the file descriptors (by replaying them with a file descriptor pointing towards /dev/null)
mitigates use after free (on file descriptor) attacks. In case some
piece of code still holds a reference to the file descriptor, that
file descriptor now merely holds a reference to /dev/null.

Otherwise, the file descriptor might be reused and the reference
could now mistakenly point to all sorts of – potentially more harmful – files, such as memfd_secret
file descriptors, storing our secret keys.
2024-08-05 16:16:09 +02:00
Karolin Varner
4bcd38a4ea feat: Infrastructure for the Rosenpass API 2024-08-03 16:51:18 +02:00
Karolin Varner
730a03957a feat: A variety of utilities in preparation for implementing the API 2024-08-03 16:50:21 +02:00
Karolin Varner
ea071f5363 feat: Convenience functions and traits to automatically handle ErrorKind::{Interrupt, WouldBlock} 2024-08-03 16:49:02 +02:00
Karolin Varner
3063d3e4c2 feat: Convenience traits to get the ErrorKind of an io error for match clauses 2024-08-03 16:48:25 +02:00
Karolin Varner
1bf0eed90a feat: Convenience function to just call a function 2024-08-03 16:46:48 +02:00
Karolin Varner
138e6b6553 chore: to crate documentation indendation (purely cosmetic) 2024-08-03 16:32:02 +02:00
Karolin Varner
2dde0a2b47 chore: Refactor integration_tests (purely cosmetic) 2024-08-03 16:31:19 +02:00
Karolin Varner
3cc3b6009f chore: Move CliCommand::run -> CliArgs::run; do not mutate the configuration
This way CliArgs::run has access to all command line parameters.
Avoided mutating the CliArgs (or rather CliCommand) structure here,
because doing so is simply bad style. There is no good reasoning for
why this function should mutate CliCommand, except for a bit of
convenience.
2024-08-03 16:29:19 +02:00
Karolin Varner
1ab457ed37 fix: Print stack trace to errors propagated to main function 2024-08-03 15:50:14 +02:00
Karolin Varner
c9c266fe7c fix: Flush stdout after printing key update notification
Otherwise, the notification might not be delivered due to buffering.
2024-08-03 15:50:14 +02:00
Karolin Varner
8d3c8790fe chore: Reorganize memfd secret policy
- Policy is now set in main.rs, not cli.rs.
- Feature is called experiment_memfd_secret, not enable_memfd_alloc

This also fixes the last remaining warnings.
2024-08-03 15:17:09 +02:00
Karolin Varner
648a94ead8 chore: Clippy fixes on wireguard-broker 2024-08-03 15:02:49 +02:00
Karolin Varner
54ac5eecdb chore: Warnings & clippy hints 2024-08-03 14:13:03 +02:00
Karolin Varner
40c5bbd167 chore: Ensure that rustAnalyzer is installed in dev environment 2024-08-03 14:06:19 +02:00
Karolin Varner
a4b8fc2226 chore: Move memcmp test API doc to test memcmp test module 2024-08-03 14:05:22 +02:00
Karolin Varner
37f7b3e4e9 fix: Consistently use feature flag experiment_libcrux
Before this, some parts of the code used an incorrect feature flag
name, preventing libcrux from being used.
2024-08-03 14:03:31 +02:00
Karolin Varner
deafc1c1af chore: Style adjustments – Cargo.toml 2024-08-03 14:03:31 +02:00
Karolin Varner
6bbe85a57b chore: Remove unnecessary imports 2024-08-03 13:59:55 +02:00
Karolin Varner
e70c5b33a8 chore: Ignore vscode directory 2024-08-03 13:35:31 +02:00
dependabot[bot]
25fdfef4d0 build(deps): bump clap from 4.5.11 to 4.5.13 (#384)
Bumps [clap](https://github.com/clap-rs/clap) from 4.5.11 to 4.5.13.
- [Release notes](https://github.com/clap-rs/clap/releases)
- [Changelog](https://github.com/clap-rs/clap/blob/master/CHANGELOG.md)
- [Commits](https://github.com/clap-rs/clap/compare/clap_complete-v4.5.11...v4.5.13)

---
updated-dependencies:
- dependency-name: clap
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-08-01 09:47:20 +02:00
dependabot[bot]
6ab8fafe59 build(deps): bump clap from 4.5.9 to 4.5.11
Bumps [clap](https://github.com/clap-rs/clap) from 4.5.9 to 4.5.11.
- [Release notes](https://github.com/clap-rs/clap/releases)
- [Changelog](https://github.com/clap-rs/clap/blob/master/CHANGELOG.md)
- [Commits](https://github.com/clap-rs/clap/compare/clap_complete-v4.5.9...v4.5.11)

---
updated-dependencies:
- dependency-name: clap
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-07-29 14:28:22 +02:00
dependabot[bot]
c1aacf76b8 build(deps): bump mio from 0.8.11 to 1.0.1 (#380)
Bumps [mio](https://github.com/tokio-rs/mio) from 0.8.11 to 1.0.1.
- [Release notes](https://github.com/tokio-rs/mio/releases)
- [Changelog](https://github.com/tokio-rs/mio/blob/master/CHANGELOG.md)
- [Commits](https://github.com/tokio-rs/mio/commits)

---
updated-dependencies:
- dependency-name: mio
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-07-27 15:59:48 +02:00
dependabot[bot]
1bcaf5781f build(deps): bump tokio from 1.38.1 to 1.39.1
Bumps [tokio](https://github.com/tokio-rs/tokio) from 1.38.1 to 1.39.1.
- [Release notes](https://github.com/tokio-rs/tokio/releases)
- [Commits](https://github.com/tokio-rs/tokio/compare/tokio-1.38.1...tokio-1.39.1)

---
updated-dependencies:
- dependency-name: tokio
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-07-25 19:05:30 +02:00
Paul Spooren
de60e5f8f0 Docs: run prettier over CONTRIBUTING.md
... or else the CI fails on all PRs

Signed-off-by: Paul Spooren <mail@aparcar.org>
2024-07-25 15:56:54 +02:00
Alice Bowman
b50ddda151 Documentation: pointed to website documentation in readme 2024-07-23 10:46:52 +02:00
Alice Bowman
7282fba3b3 Docs: migrated cooking recipe from wiki 2024-07-23 10:41:44 +02:00
dependabot[bot]
0cca389f10 build(deps): bump thiserror from 1.0.62 to 1.0.63 (#371)
Bumps [thiserror](https://github.com/dtolnay/thiserror) from 1.0.62 to 1.0.63.
- [Release notes](https://github.com/dtolnay/thiserror/releases)
- [Commits](https://github.com/dtolnay/thiserror/compare/1.0.62...1.0.63)

---
updated-dependencies:
- dependency-name: thiserror
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-07-18 14:29:08 +02:00
Karolin Varner
8a08d49215 Merge pull request #370 from rosenpass/dependabot/cargo/tokio-1.38.1
build(deps): bump tokio from 1.38.0 to 1.38.1
2024-07-17 08:35:06 +02:00
dependabot[bot]
8637bc7884 build(deps): bump tokio from 1.38.0 to 1.38.1
Bumps [tokio](https://github.com/tokio-rs/tokio) from 1.38.0 to 1.38.1.
- [Release notes](https://github.com/tokio-rs/tokio/releases)
- [Commits](https://github.com/tokio-rs/tokio/compare/tokio-1.38.0...tokio-1.38.1)

---
updated-dependencies:
- dependency-name: tokio
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-07-16 23:32:14 +00:00
dependabot[bot]
4412c2bdd1 build(deps): bump thiserror from 1.0.61 to 1.0.62 (#366)
Bumps [thiserror](https://github.com/dtolnay/thiserror) from 1.0.61 to 1.0.62.
- [Release notes](https://github.com/dtolnay/thiserror/releases)
- [Commits](https://github.com/dtolnay/thiserror/compare/1.0.61...1.0.62)

---
updated-dependencies:
- dependency-name: thiserror
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-07-12 14:28:18 +02:00
Karolin Varner
ecc815dd8e Merge pull request #363 from aparcar/regression-ci
Regression CI and fixup
2024-07-10 21:09:16 +02:00
Paul Spooren
b7d7c03e35 Merge branch 'main' into regression-ci 2024-07-10 20:06:33 +02:00
Paul Spooren
f6320c3c35 ci: fixup regression test
Signed-off-by: Paul Spooren <mail@aparcar.org>
2024-07-10 18:57:45 +02:00
Karolin Varner
19f7905bc9 Merge pull request #362 from rosenpass/dev/karo/libcrux_chacha20poly1305
feat: Experimental support for encryption using libcrux
2024-07-10 15:08:31 +02:00
Karolin Varner
9b5b7ee620 Merge pull request #338 from aparcar/no-unused
drop unused import of WG_B64_LEN
2024-07-10 15:04:35 +02:00
dependabot[bot]
4fdd271de7 build(deps): bump clap from 4.5.8 to 4.5.9 (#365)
Bumps [clap](https://github.com/clap-rs/clap) from 4.5.8 to 4.5.9.
- [Release notes](https://github.com/clap-rs/clap/releases)
- [Changelog](https://github.com/clap-rs/clap/blob/master/CHANGELOG.md)
- [Commits](https://github.com/clap-rs/clap/compare/v4.5.8...v4.5.9)

---
updated-dependencies:
- dependency-name: clap
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-07-10 14:17:45 +02:00
dependabot[bot]
860e65965a build(deps): bump serde from 1.0.203 to 1.0.204 (#364)
Bumps [serde](https://github.com/serde-rs/serde) from 1.0.203 to 1.0.204.
- [Release notes](https://github.com/serde-rs/serde/releases)
- [Commits](https://github.com/serde-rs/serde/compare/v1.0.203...v1.0.204)

---
updated-dependencies:
- dependency-name: serde
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-07-09 09:08:54 +02:00
Prabhpreet Dua
87144233da Prettier 2024-07-08 13:54:26 +02:00
Prabhpreet Dua
d0a6e99a1f feat: Regression CI based on misc/generate_configs.py 2024-07-08 13:54:26 +02:00
Paul Spooren
79b634fadf drop unused import of WG_B64_LEN
This causes warnings

Signed-off-by: Paul Spooren <mail@aparcar.org>
2024-07-08 13:48:00 +02:00
Karolin Varner
99ac3c0902 feat: Experimental support for encryption using libcrux
Libcrux is a library for formally verified implementations of
cryptographic primitives. It uses multiple back ends; one of which is
libjade. A cryptographic library written in the jasmin assembly
language for high assurance cryptographic implementations.

To use compile with the experiment_libcrux feature enabled:

    cargo build --features experiment_libcrux
2024-07-03 21:46:40 +02:00
dependabot[bot]
010c14dadf build(deps): bump zerocopy from 0.7.34 to 0.7.35 (#361)
Bumps [zerocopy](https://github.com/google/zerocopy) from 0.7.34 to 0.7.35.
- [Release notes](https://github.com/google/zerocopy/releases)
- [Changelog](https://github.com/google/zerocopy/blob/main/CHANGELOG.md)
- [Commits](https://github.com/google/zerocopy/commits)

---
updated-dependencies:
- dependency-name: zerocopy
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-07-03 11:08:42 +02:00
dependabot[bot]
45b6132312 build(deps): bump clap from 4.5.7 to 4.5.8 (#360)
Bumps [clap](https://github.com/clap-rs/clap) from 4.5.7 to 4.5.8.
- [Release notes](https://github.com/clap-rs/clap/releases)
- [Changelog](https://github.com/clap-rs/clap/blob/master/CHANGELOG.md)
- [Commits](https://github.com/clap-rs/clap/compare/clap_complete-v4.5.7...v4.5.8)

---
updated-dependencies:
- dependency-name: clap
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-06-29 20:18:42 +02:00
dependabot[bot]
77f9fd38f3 build(deps): bump log from 0.4.21 to 0.4.22 (#359)
Bumps [log](https://github.com/rust-lang/log) from 0.4.21 to 0.4.22.
- [Release notes](https://github.com/rust-lang/log/releases)
- [Changelog](https://github.com/rust-lang/log/blob/master/CHANGELOG.md)
- [Commits](https://github.com/rust-lang/log/compare/0.4.21...0.4.22)

---
updated-dependencies:
- dependency-name: log
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-06-29 20:17:25 +02:00
Karolin Varner
775ed86adc Merge pull request #356 from pqcfox/hotfix/fix-kyber-encaps-fuzz-test
Fix Kyber encapsulation fuzz test shared key length to make test pass
2024-06-28 16:59:05 +02:00
Katherine Watson
40377dce1f fix: Fix shared_secret length in Kyber encaps fuzz test 2024-06-27 09:17:05 -07:00
Karolin Varner
19293471e8 Merge pull request #357 from rosenpass/dev/cve/new_name
meta: Use my new name
2024-06-27 11:15:52 +02:00
Clara Engler
cc5877dd83 meta: Use my new name 2024-06-27 10:30:34 +02:00
Karolin Varner
ebb591aa6f Merge pull request #354 from pqcfox/hotfix/fix-static-kem-branch-errors
Fix CI after merge of branch introducing PublicBox
2024-06-25 08:57:50 +02:00
Katherine Watson
07146d9914 fix: update handle_msg.rs fuzz test and handshake.rs bench to use PublicBox 2024-06-21 18:21:33 -07:00
Karolin Varner
cd04dbc4eb Move static KEM public key to new PublicBox struct 2024-06-21 13:06:05 +02:00
Katherine Watson
cc22165dc4 chore: Ensure punctuation is consistent in doc comments 2024-06-17 20:53:19 -07:00
Katherine Watson
8496571765 test: Modify existing tests to cover load/store for PublicBox as well 2024-06-17 20:49:40 -07:00
Katherine Watson
ee3a1f580e Refactor PublicBox to reuse Public code and minimize stack overhead 2024-06-17 20:49:40 -07:00
Katherine Watson
89584645c3 Migrate PublicBox to above tests 2024-06-17 20:49:40 -07:00
Katherine Watson
3286e49370 Replace &* incantations with .deref() 2024-06-17 20:49:40 -07:00
Karolin Varner
100d7b6e1c chore: Simplify some dereferencing incantations in PublicBox 2024-06-17 20:49:40 -07:00
Katherine Watson
921b2bfc39 Fix comments in PublicBox impl to refer to PublicBox 2024-06-17 20:49:40 -07:00
Katherine Watson
a18658847c Move static KEM public key to new PublicBox struct 2024-06-17 20:49:40 -07:00
Alice Michaela Bowman
bdad414c90 Add cargo-test runner for macos x86-64 (#348)
* added cargo-test runner for macos 86-64
---------

Co-authored-by: Prabhpreet Dua <615318+prabhpreet@users.noreply.github.com>
2024-06-17 15:48:19 +02:00
Paul Spooren
7c54a37618 misc: add generate_configs.py script
The script can be used to simulate setups of different sizes. A short
description is added to the `misc/` folder for further information.

This can be used for both benchmarking but also hunting down bugs which
may occur with larger setups.

Signed-off-by: Paul Spooren <mail@aparcar.org>
2024-06-13 11:11:53 +02:00
Prabhpreet Dua
7a4f700186 feat: Improved memfd-secret allocation (#347)
Improve memfd-secret guard page allocation by using combination of mmap to map allocation area, and nest memfd-secret mapping and meta information with different permissions within the area

Implemented in quininer/memsec#18 

Co-authored-by: Prabhpreet Dua <615318+prabhpreet@users.noreply.github.com>
Co-authored-by: Karolin Varner <karo@cupdev.net>
2024-06-13 10:04:35 +05:30
Prabhpreet Dua
f535a31cd7 Feature flag for memfd_secret alloc (#343)
* feature flag for memfd_secret alloc

* Cargo fmt
2024-06-11 14:53:30 +05:30
Karolin Varner
ac2aaa5fbd Merge pull request #336 from rosenpass/dev/karo/rollback-proofs
chore: Rollback symbolic models to original state
2024-06-11 09:57:36 +02:00
dependabot[bot]
e472fa1fcd build(deps): bump clap from 4.5.6 to 4.5.7 (#340)
Bumps [clap](https://github.com/clap-rs/clap) from 4.5.6 to 4.5.7.
- [Release notes](https://github.com/clap-rs/clap/releases)
- [Changelog](https://github.com/clap-rs/clap/blob/master/CHANGELOG.md)
- [Commits](https://github.com/clap-rs/clap/compare/v4.5.6...v4.5.7)

---
updated-dependencies:
- dependency-name: clap
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-06-11 08:26:40 +05:30
Prabhpreet Dua
526c930119 Secret memory with memfd_secret (#321)
Implements:
- An additional allocator to use memfd_secret(2) and guard pages using mmap(2), implemented in quininer/memsec#16
- An allocator that abstracts away underlying allocators, and uses specified allocator set by rosenpass_secret_memory::policy functions (or a function that sets rosenpass_secret_memory::alloc::ALLOC_INIT
- Updates to tests- integration, fuzz, bench: some tests use procspawn to spawn multiple processes with different allocator policies
2024-06-10 13:12:44 +05:30
Karolin Varner
5f8b00d045 chore: Rollback symbolic models to original state
The later edits where unfortunately incomplete. They lacked
modeling of multi-session, multi-user settings and they generally
rendered the models less trustworthy from my perspective.

These edits are still interesting as a starting point for analyzing
identity hiding and stealth, but they are not high-quality enough to be
present in main.
2024-06-07 20:05:23 +02:00
dependabot[bot]
b46fca99cb build(deps): bump clap from 4.5.4 to 4.5.6 (#335)
Bumps [clap](https://github.com/clap-rs/clap) from 4.5.4 to 4.5.6.
- [Release notes](https://github.com/clap-rs/clap/releases)
- [Changelog](https://github.com/clap-rs/clap/blob/master/CHANGELOG.md)
- [Commits](https://github.com/clap-rs/clap/compare/clap_complete-v4.5.4...v4.5.6)

---
updated-dependencies:
- dependency-name: clap
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-06-07 10:46:02 +05:30
Prabhpreet Dua
70c5ec2c29 chore: Remove libsodium references in nix flake, ci (#334) 2024-06-06 17:10:51 +05:30
Prabhpreet Dua
0e059af5da fix(rosenpass): Fix duplicate key issue (#329)
Change handle_init_conf to return to instruct key exchange on encountering new biscuit_no for peer
2024-06-04 22:47:54 +05:30
Paul Spooren
99754f326e Warn only if neither peer nor outfile is defined
Right now a warning message is logged if no Wireguard peer is defined.
This is misleading in cases where the outfile is used instead.

Signed-off-by: Paul Spooren <mail@aparcar.org>
2024-06-03 17:58:50 +02:00
dependabot[bot]
fd397b9ea0 build(deps): bump tokio from 1.37.0 to 1.38.0 (#324)
Bumps [tokio](https://github.com/tokio-rs/tokio) from 1.37.0 to 1.38.0.
- [Release notes](https://github.com/tokio-rs/tokio/releases)
- [Commits](https://github.com/tokio-rs/tokio/compare/tokio-1.37.0...tokio-1.38.0)

---
updated-dependencies:
- dependency-name: tokio
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-05-31 08:30:41 +05:30
dependabot[bot]
e92fa552e3 build(deps): bump zeroize from 1.7.0 to 1.8.1 (#322)
Bumps [zeroize](https://github.com/RustCrypto/utils) from 1.7.0 to 1.8.1.
- [Commits](https://github.com/RustCrypto/utils/compare/zeroize-v1.7.0...zeroize-v1.8.1)

---
updated-dependencies:
- dependency-name: zeroize
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Prabhpreet Dua <615318+prabhpreet@users.noreply.github.com>
2024-05-28 14:23:45 +05:30
dependabot[bot]
c438d5a99d build(deps): bump serde from 1.0.202 to 1.0.203 (#323)
Bumps [serde](https://github.com/serde-rs/serde) from 1.0.202 to 1.0.203.
- [Release notes](https://github.com/serde-rs/serde/releases)
- [Commits](https://github.com/serde-rs/serde/compare/v1.0.202...v1.0.203)

---
updated-dependencies:
- dependency-name: serde
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-05-28 11:07:24 +05:30
dependabot[bot]
d4eef998f5 --- (#318)
updated-dependencies:
- dependency-name: anyhow
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-05-21 07:12:19 +05:30
Prabhpreet Dua
c1abfbfd14 feat(rosenpass): Add wireguard-broker interface in AppServer (#303)
Dynamically dispatch WireguardBrokerMio trait in AppServer. Also allows for mio event registration and poll processing, logic from dev/broker-architecture branch

Co-authored-by: Prabhpreet Dua <615318+prabhpreet@users.noreply.github.com>
Co-authored-by: Karolin Varner <karo@cupdev.net>
2024-05-20 18:12:42 +05:30
dependabot[bot]
ae7577c641 build(deps): bump thiserror from 1.0.60 to 1.0.61 (#316)
Bumps [thiserror](https://github.com/dtolnay/thiserror) from 1.0.60 to 1.0.61.
- [Release notes](https://github.com/dtolnay/thiserror/releases)
- [Commits](https://github.com/dtolnay/thiserror/compare/1.0.60...1.0.61)

---
updated-dependencies:
- dependency-name: thiserror
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-05-18 12:39:10 +02:00
dependabot[bot]
f07f598e44 build(deps): bump anyhow from 1.0.83 to 1.0.85 (#317)
Bumps [anyhow](https://github.com/dtolnay/anyhow) from 1.0.83 to 1.0.85.
- [Release notes](https://github.com/dtolnay/anyhow/releases)
- [Commits](https://github.com/dtolnay/anyhow/compare/1.0.83...1.0.85)

---
updated-dependencies:
- dependency-name: anyhow
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-05-18 12:38:46 +02:00
Alice Michaela Bowman
988f66cf2b Merge pull request #314 from prabhpreet/fix/dep-workflow-permissions
chore: Add write permissions in dependent-issues workflow
2024-05-17 11:48:20 +02:00
Prabhpreet Dua
06969c406d chore: Add write permissions in dependent-issues workflow 2024-05-17 14:56:29 +05:30
dependabot[bot]
b5215aecba build(deps): bump serde from 1.0.201 to 1.0.202 (#312)
Bumps [serde](https://github.com/serde-rs/serde) from 1.0.201 to 1.0.202.
- [Release notes](https://github.com/serde-rs/serde/releases)
- [Commits](https://github.com/serde-rs/serde/compare/v1.0.201...v1.0.202)

---
updated-dependencies:
- dependency-name: serde
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-05-16 14:18:26 +05:30
Alice Michaela Bowman
3e32bbad7c Merge pull request #310 from rosenpass/ci/dependent-issues
Dependent issues Workflow
2024-05-10 16:42:34 +02:00
Prabhpreet Dua
650110a04f Run prettier (#311) 2024-05-10 19:55:29 +05:30
Prabhpreet Dua
ee669823de Create dependent-issues.yml 2024-05-10 19:47:10 +05:30
dependabot[bot]
40940ca1df build(deps): bump serde from 1.0.200 to 1.0.201 (#307)
Bumps [serde](https://github.com/serde-rs/serde) from 1.0.200 to 1.0.201.
- [Release notes](https://github.com/serde-rs/serde/releases)
- [Commits](https://github.com/serde-rs/serde/compare/v1.0.200...v1.0.201)

---
updated-dependencies:
- dependency-name: serde
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-05-09 07:41:30 +05:30
dependabot[bot]
b77eccffc0 build(deps): bump paste from 1.0.14 to 1.0.15 (#304)
Bumps [paste](https://github.com/dtolnay/paste) from 1.0.14 to 1.0.15.
- [Release notes](https://github.com/dtolnay/paste/releases)
- [Commits](https://github.com/dtolnay/paste/compare/1.0.14...1.0.15)

---
updated-dependencies:
- dependency-name: paste
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-05-08 11:02:31 +05:30
dependabot[bot]
e17d8cd559 build(deps): bump thiserror from 1.0.59 to 1.0.60 (#305)
Bumps [thiserror](https://github.com/dtolnay/thiserror) from 1.0.59 to 1.0.60.
- [Release notes](https://github.com/dtolnay/thiserror/releases)
- [Commits](https://github.com/dtolnay/thiserror/compare/1.0.59...1.0.60)

---
updated-dependencies:
- dependency-name: thiserror
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Prabhpreet Dua <615318+prabhpreet@users.noreply.github.com>
2024-05-08 10:24:19 +05:30
dependabot[bot]
c72e8bcda1 build(deps): bump zerocopy from 0.7.33 to 0.7.34 (#306)
Bumps [zerocopy](https://github.com/google/zerocopy) from 0.7.33 to 0.7.34.
- [Release notes](https://github.com/google/zerocopy/releases)
- [Changelog](https://github.com/google/zerocopy/blob/main/CHANGELOG.md)
- [Commits](https://github.com/google/zerocopy/commits)

---
updated-dependencies:
- dependency-name: zerocopy
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-05-08 10:06:29 +05:30
Prabhpreet Dua
2bac991305 feat(wireguard-broker): merge from dev/broker-architecture, fixes, test
* wireguard-broker: merge from dev/broker-architecture
* use zerocopy instead of lenses
* Require use_broker feature flag to comile broker binaries
* Remove PhantomData from BrokerServer & BrokerClient
* Modify mio client rx to be non-recursive, add integration test

Co-authored-by: Karolin Varner <karo@cupdev.net>
Co-authored-by: Prabhpreet Dua <615318+prabhpreet@users.noreply.github.com>
2024-05-07 12:23:35 +05:30
dependabot[bot]
e6d114c557 build(deps): bump zerocopy from 0.7.32 to 0.7.33 (#301)
Bumps [zerocopy](https://github.com/google/zerocopy) from 0.7.32 to 0.7.33.
- [Release notes](https://github.com/google/zerocopy/releases)
- [Changelog](https://github.com/google/zerocopy/blob/main/CHANGELOG.md)
- [Commits](https://github.com/google/zerocopy/compare/v0.7.32...v0.7.33)

---
updated-dependencies:
- dependency-name: zerocopy
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-05-07 08:35:36 +05:30
dependabot[bot]
29efbba97a build(deps): bump anyhow from 1.0.82 to 1.0.83 (#302)
Bumps [anyhow](https://github.com/dtolnay/anyhow) from 1.0.82 to 1.0.83.
- [Release notes](https://github.com/dtolnay/anyhow/releases)
- [Commits](https://github.com/dtolnay/anyhow/compare/1.0.82...1.0.83)

---
updated-dependencies:
- dependency-name: anyhow
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-05-07 08:34:59 +05:30
Karolin Varner
3fb1220262 Merge pull request #300 from prabhpreet/codecov-yml
chore: Add codecov configuration file
2024-05-06 17:59:27 +02:00
Prabhpreet Dua
1ccf92c538 Merge branch 'main' into codecov-yml 2024-05-06 21:14:29 +05:30
Prabhpreet Dua
4bb3153761 feat(deps): Change base64 to base64ct crate (#295) 2024-05-06 21:14:10 +05:30
Prabhpreet Dua
a8ed0e8c66 chore: Update codecov configuration file 2024-05-06 20:59:08 +05:30
Prabhpreet Dua
ad6405f865 chore: Add codecov configuration file 2024-05-06 20:53:55 +05:30
Prabhpreet Dua
761d5730af ci: Changes from #160- Invoke the mandoc linter (#296)
* ci: Changes from #160- Invoke the mandoc linter

* Add check.sh from #160 too

* Fix mandoc
2024-05-04 22:47:11 +02:00
Prabhpreet Dua
b45b7bc7f5 Update liboqs 0.9.1 (#292)
* deps,fuzz: update to liboqs 0.9.1

The release updates the Classic McEliece to NIST PQC Round 4 version
Updates breaking fuzz tests as well

Signed-off-by:
Paul Spooren <mail@aparcar.org>
Prabhpreet Dua <615318+prabhpreet@users.noreply.github.com>

* Update secret key length for McEliece KEM update

* Update to specifying key lengths of Kyber and McEliece through constants

---------

Co-authored-by: Paul Spooren <mail@aparcar.org>
2024-05-02 18:47:26 +05:30
dependabot[bot]
77a985dc02 build(deps): bump serde from 1.0.199 to 1.0.200 (#299)
Bumps [serde](https://github.com/serde-rs/serde) from 1.0.199 to 1.0.200.
- [Release notes](https://github.com/serde-rs/serde/releases)
- [Commits](https://github.com/serde-rs/serde/compare/v1.0.199...v1.0.200)

---
updated-dependencies:
- dependency-name: serde
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-05-02 13:10:47 +05:30
Prabhpreet Dua
21e693a9da ci: Add codecov (llvm-cov) coverage (#297)
* ci: Add codecov (llvm-cov) coverage

* Run prettier on qc.yaml
2024-05-01 18:31:46 +05:30
Emil Engler
be91b3049c rp: Load WireGuard SK into secret memory (#293)
Fixes #287
2024-04-30 18:10:04 +02:00
dependabot[bot]
4dc24f745c build(deps): bump serial_test from 3.1.0 to 3.1.1 (#290)
Bumps [serial_test](https://github.com/palfrey/serial_test) from 3.1.0 to 3.1.1.
- [Release notes](https://github.com/palfrey/serial_test/releases)
- [Commits](https://github.com/palfrey/serial_test/compare/v3.1.0...v3.1.1)

---
updated-dependencies:
- dependency-name: serial_test
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-04-30 14:51:24 +05:30
dependabot[bot]
61a1cc3825 build(deps): bump serde from 1.0.198 to 1.0.199 (#291)
Bumps [serde](https://github.com/serde-rs/serde) from 1.0.198 to 1.0.199.
- [Release notes](https://github.com/serde-rs/serde/releases)
- [Commits](https://github.com/serde-rs/serde/compare/v1.0.198...v1.0.199)

---
updated-dependencies:
- dependency-name: serde
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-04-30 13:22:37 +05:30
Prabhpreet Dua
2e01d1df46 Revert "build(deps): bump zeroize from 1.7.0 to 1.8.0 (#285)" (#289)
Reverts #285 since 1.8.0 has been yanked

Refer RustCrypto/utils#1067
2024-04-29 14:06:34 +05:30
Prabhpreet Dua
2c6411a2b1 Merge pull request #284 from rosenpass/dependabot/cargo/serial_test-3.1.0
build(deps): bump serial_test from 3.0.0 to 3.1.0
2024-04-29 12:47:04 +05:30
Karolin Varner
96b12ac261 Clippy Fixes 2024-04-25 20:32:46 +02:00
Emil Engler
3e734e0d57 rosenpass: Replace Into<> with From<> trait 2024-04-25 11:16:52 +02:00
Emil Engler
c9e296794b rosenpass: Remove useless conversion 2024-04-25 11:15:51 +02:00
Emil Engler
bc6bff499d rosenpass: Remove redundant Ok() 2024-04-25 11:14:59 +02:00
Emil Engler
de905056fc rp: Remove needless borrow 2024-04-25 11:13:32 +02:00
Emil Engler
4e8344660e rosenpass: Remove needless borrow 2024-04-25 11:11:56 +02:00
Emil Engler
a581f7dfa7 rosenpass: Replace if let with is_ok() call 2024-04-25 11:10:21 +02:00
Emil Engler
bd6a6e5dce ciphers: Remove needless borrow for nonce array 2024-04-25 11:08:54 +02:00
Emil Engler
e0496c12c6 rosenpass: Use copy instead of clone trait 2024-04-25 11:05:16 +02:00
Emil Engler
f4116f2c20 ciphers: Remove redundant mutability 2024-04-25 11:03:48 +02:00
Emil Engler
8099bc4bdd constant-time: Remove redundant cast 2024-04-25 11:01:41 +02:00
Emil Engler
39d174c605 util: Suppress clippy warnings for neutral element 2024-04-25 11:01:09 +02:00
dependabot[bot]
0257aa9e15 build(deps): bump zeroize from 1.7.0 to 1.8.0 (#285)
Bumps [zeroize](https://github.com/RustCrypto/utils) from 1.7.0 to 1.8.0.
- [Commits](https://github.com/RustCrypto/utils/compare/zeroize-v1.7.0...zeroize-v1.8.0)

---
updated-dependencies:
- dependency-name: zeroize
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-04-25 10:54:55 +02:00
Emil Engler
3299b2bdb4 Merge branch 'main' into dependabot/cargo/serial_test-3.1.0 2024-04-23 11:15:57 +02:00
dependabot[bot]
f43b018511 build(deps): bump thiserror from 1.0.58 to 1.0.59 (#283)
Bumps [thiserror](https://github.com/dtolnay/thiserror) from 1.0.58 to 1.0.59.
- [Release notes](https://github.com/dtolnay/thiserror/releases)
- [Commits](https://github.com/dtolnay/thiserror/compare/1.0.58...1.0.59)

---
updated-dependencies:
- dependency-name: thiserror
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-04-23 11:15:28 +02:00
dependabot[bot]
0f884b79fa build(deps): bump serial_test from 3.0.0 to 3.1.0
Bumps [serial_test](https://github.com/palfrey/serial_test) from 3.0.0 to 3.1.0.
- [Release notes](https://github.com/palfrey/serial_test/releases)
- [Commits](https://github.com/palfrey/serial_test/compare/v3.0.0...v3.1.0)

---
updated-dependencies:
- dependency-name: serial_test
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-04-22 23:31:58 +00:00
dependabot[bot]
ab83d3fae6 build(deps): bump tempfile from 3.9.0 to 3.10.1 (#282)
Bumps [tempfile](https://github.com/Stebalien/tempfile) from 3.9.0 to 3.10.1.
- [Changelog](https://github.com/Stebalien/tempfile/blob/master/CHANGELOG.md)
- [Commits](https://github.com/Stebalien/tempfile/compare/v3.9.0...v3.10.1)

---
updated-dependencies:
- dependency-name: tempfile
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-04-20 17:46:35 +02:00
Gergő Móricz
cc7e8dc510 feat(rp-rust): implement rp tool in Rust (#235) 2024-04-19 20:44:55 +02:00
Gergő Móricz
c2d0d34c57 Add .devcontainer configuration (#267)
chore: Devcontainer config
2024-04-19 14:50:46 +02:00
Alice Michaela Bowman
5d46c93b2b Merge pull request #142 from prabhpreet/feat/cookie-mechanism
Add cookie mechanism
2024-04-17 13:48:14 +02:00
Prabhpreet Dua
e6d7a7232f Cargo lock update 2024-04-16 17:54:03 +05:30
Prabhpreet Dua
6ba1be6eae Merge branch 'main' into feat/cookie-mechanism 2024-04-16 17:41:41 +05:30
dependabot[bot]
c194c74e55 build(deps): bump clap from 4.4.10 to 4.5.4
Bumps [clap](https://github.com/clap-rs/clap) from 4.4.10 to 4.5.4.
- [Release notes](https://github.com/clap-rs/clap/releases)
- [Changelog](https://github.com/clap-rs/clap/blob/master/CHANGELOG.md)
- [Commits](https://github.com/clap-rs/clap/compare/clap_complete-v4.4.10...v4.5.4)

---
updated-dependencies:
- dependency-name: clap
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-04-16 12:19:01 +02:00
dependabot[bot]
96de84e68f build(deps): bump allocator-api2-tests from 0.2.14 to 0.2.15
Bumps [allocator-api2-tests](https://github.com/zakarumych/allocator-api2) from 0.2.14 to 0.2.15.
- [Changelog](https://github.com/zakarumych/allocator-api2/blob/main/CHANGELOG.md)
- [Commits](https://github.com/zakarumych/allocator-api2/compare/v0.2.14...v0.2.15)

---
updated-dependencies:
- dependency-name: allocator-api2-tests
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-04-16 12:18:50 +02:00
Prabhpreet Dua
6215bc1514 Update whitepaper 2024-04-16 15:24:08 +05:30
Prabhpreet Dua
b0a93d6884 Whitepaper and cleanup 2024-04-16 15:07:01 +05:30
Prabhpreet Dua
bba0c874f2 Localhost ::1 2024-04-16 13:21:55 +05:30
Prabhpreet Dua
a32efb61d1 Skip cookie validation with InitConf, use 0.0.0.0 for loopback 2024-04-16 12:57:01 +05:30
Prabhpreet Dua
10bdb5f371 Display error if send to socket fails 2024-04-16 12:41:40 +05:30
Prabhpreet Dua
b07859f6ec Change under load params, change localhost to IP 2024-04-16 12:16:30 +05:30
Prabhpreet Dua
65df24a98b Consolidate tests with debugging 2024-04-16 11:41:43 +05:30
Prabhpreet Dua
9396784c0f Cargo fmt 2024-04-16 11:18:47 +05:30
Prabhpreet Dua
8420d953eb Add HostIdentification trait, add logging 2024-04-16 11:17:03 +05:30
Prabhpreet Dua
e7de4848fb Try threads instead of process 2024-04-16 09:22:08 +05:30
Prabhpreet Dua
92824bb5b0 Integration test- add delay between server and client 2024-04-16 06:55:24 +05:30
Prabhpreet Dua
8d20e77173 Serialize integration tests 2024-04-16 06:45:05 +05:30
Prabhpreet Dua
15aafe7563 Cargo fmt fix 2024-04-15 22:13:14 +05:30
Prabhpreet Dua
b56af8b696 Simplify integration test 2024-04-15 22:10:40 +05:30
Prabhpreet Dua
a3e91a95df Fix post merge integration test issue 2024-04-15 14:25:09 +05:30
Prabhpreet Dua
4ea51ab123 Merge branch 'main' into feat/cookie-mechanism 2024-04-14 18:53:51 +05:30
dependabot[bot]
4b849a4fe4 build(deps): bump anyhow from 1.0.81 to 1.0.82
Bumps [anyhow](https://github.com/dtolnay/anyhow) from 1.0.81 to 1.0.82.
- [Release notes](https://github.com/dtolnay/anyhow/releases)
- [Commits](https://github.com/dtolnay/anyhow/compare/1.0.81...1.0.82)

---
updated-dependencies:
- dependency-name: anyhow
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-04-11 11:47:09 +02:00
dependabot[bot]
16e67269ba build(deps): bump thiserror from 1.0.50 to 1.0.58
Bumps [thiserror](https://github.com/dtolnay/thiserror) from 1.0.50 to 1.0.58.
- [Release notes](https://github.com/dtolnay/thiserror/releases)
- [Commits](https://github.com/dtolnay/thiserror/compare/1.0.50...1.0.58)

---
updated-dependencies:
- dependency-name: thiserror
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-04-11 11:46:59 +02:00
wucke13
76d5093a20 chore: apply .ci/gen-workflow-files.nu script
There is still hand-written stuff in the workflow file that we need to
get rid of, but now at least all autogenerated dependency fields are
sorted.
2024-04-06 17:45:34 +02:00
wucke13
0e8945db78 fix: .ci/gen-workflow-files.nu script
- Fix std log import (remove the asterisk)
- Add sort to dependencies field to make script output deterministic
- Remove whitespace error at EOF
- Add nushell to the default devShell, so that the script can be ran
  from the devShell
2024-04-06 17:45:34 +02:00
wucke13
ffd81b6a72 chore: update flake.lock
Six months passed, time to get up-to-date again.
2024-04-06 17:45:34 +02:00
wucke13
d1d218ac0f chore: add dedicated nixpkgs input to flake
This ensures that `nix flake update` doesn't create surprises on
different systems.
2024-04-06 17:45:34 +02:00
dependabot[bot]
0edfb625e8 build(deps): bump log from 0.4.20 to 0.4.21
Bumps [log](https://github.com/rust-lang/log) from 0.4.20 to 0.4.21.
- [Release notes](https://github.com/rust-lang/log/releases)
- [Changelog](https://github.com/rust-lang/log/blob/master/CHANGELOG.md)
- [Commits](https://github.com/rust-lang/log/compare/0.4.20...0.4.21)

---
updated-dependencies:
- dependency-name: log
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-04-06 15:14:03 +02:00
dependabot[bot]
16c0080cdc build(deps): bump memoffset from 0.9.0 to 0.9.1
Bumps [memoffset](https://github.com/Gilnaa/memoffset) from 0.9.0 to 0.9.1.
- [Changelog](https://github.com/Gilnaa/memoffset/blob/master/CHANGELOG.md)
- [Commits](https://github.com/Gilnaa/memoffset/compare/v0.9.0...v0.9.1)

---
updated-dependencies:
- dependency-name: memoffset
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-04-06 15:13:35 +02:00
dependabot[bot]
b05c4bbe24 build(deps): bump serde from 1.0.193 to 1.0.197
Bumps [serde](https://github.com/serde-rs/serde) from 1.0.193 to 1.0.197.
- [Release notes](https://github.com/serde-rs/serde/releases)
- [Commits](https://github.com/serde-rs/serde/compare/v1.0.193...v1.0.197)

---
updated-dependencies:
- dependency-name: serde
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-04-06 15:13:21 +02:00
dependabot[bot]
639c65ef93 build(deps): bump env_logger from 0.10.1 to 0.10.2
Bumps [env_logger](https://github.com/rust-cli/env_logger) from 0.10.1 to 0.10.2.
- [Release notes](https://github.com/rust-cli/env_logger/releases)
- [Changelog](https://github.com/rust-cli/env_logger/blob/main/CHANGELOG.md)
- [Commits](https://github.com/rust-cli/env_logger/compare/v0.10.1...v0.10.2)

---
updated-dependencies:
- dependency-name: env_logger
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-03-21 00:39:00 +01:00
dependabot[bot]
332c549305 build(deps): bump anyhow from 1.0.75 to 1.0.81
Bumps [anyhow](https://github.com/dtolnay/anyhow) from 1.0.75 to 1.0.81.
- [Release notes](https://github.com/dtolnay/anyhow/releases)
- [Commits](https://github.com/dtolnay/anyhow/compare/1.0.75...1.0.81)

---
updated-dependencies:
- dependency-name: anyhow
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-03-21 00:38:44 +01:00
dependabot[bot]
ef973e9d7f build(deps): bump base64 from 0.21.5 to 0.21.7
Bumps [base64](https://github.com/marshallpierce/rust-base64) from 0.21.5 to 0.21.7.
- [Changelog](https://github.com/marshallpierce/rust-base64/blob/master/RELEASE-NOTES.md)
- [Commits](https://github.com/marshallpierce/rust-base64/compare/v0.21.5...v0.21.7)

---
updated-dependencies:
- dependency-name: base64
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-03-21 00:38:34 +01:00
Paul Spooren
199ecb814b dependabot: add configuration
This checks daily for outdated cargo crates.

Signed-off-by: Paul Spooren <mail@aparcar.org>
2024-03-20 14:24:34 +01:00
Paul Spooren
40d955a156 proper permission for secrets aka 0o600
When creating secret keys or use the out file feature, the material
shouldn't be readble to everyone by default.

Fix: #260

Signed-off-by: Paul Spooren <mail@aparcar.org>
2024-03-20 14:24:23 +01:00
Karolin Varner
cd23e9a2d0 fix: Failing tests 2024-03-12 22:34:31 -04:00
Karolin Varner
4d482aaab7 chore: Cargo fmt & fix 2024-03-12 22:11:17 -04:00
Karolin Varner
3175b7b783 Merge branch 'main' into feat/cookie-mechanism 2024-03-12 22:08:04 -04:00
Paul Spooren
baa35af558 bench: exclude rosenpass-fuzzing
This stops fuzzing to run which takes forever and breaks the CI.

Signed-off-by: Paul Spooren <mail@aparcar.org>
2024-03-12 19:28:27 +01:00
Paul Spooren
b2de384fcf constant-time: add secure memcmp_le function
The compare function should do a little-endian comparision, therefore
copy the code from quinier/memsec and don't revert the loop, tada, le.

Signed-off-by: Paul Spooren <mail@aparcar.org>
2024-03-11 13:08:41 +01:00
Paul Spooren
c69fd889fb ci: enable cargo bench again
It only takes a few seconds to run, enable it.

Signed-off-by: Paul Spooren <mail@aparcar.org>
2024-03-11 13:08:41 +01:00
Dimitris Apostolou
13a853ff42 fix: Fix crate vulnerabilities 2024-03-10 18:11:43 +01:00
Paul Spooren
13df700ef5 flake: drop overlay due to upstream fix
Upstream fix #216904 got fixed to remove the extra overlay.

Signed-off-by: Paul Spooren <mail@aparcar.org>
2024-03-08 20:22:41 +01:00
Ilka Schulz
2e7f34f4b2 Merge pull request #253 from aparcar/welcome-home
config: drop deprecated std::env::home_dir()
2024-03-05 14:54:42 +01:00
Ilka Schulz
292b4bbae0 Merge pull request #255 from aparcar/aarch64-ci
ci: Enable aarch64-linux builds again
2024-03-05 14:51:34 +01:00
Ilka Schulz
c75d222477 Merge pull request #254 from aparcar/manual
build: add link to manual
2024-03-05 12:26:51 +01:00
Paul Spooren
478fadb80d ci: Enable aarch64-linux builds again
Signed-off-by: Paul Spooren <mail@aparcar.org>
2024-03-05 10:39:46 +01:00
Paul Spooren
7c1ada4b10 build: add link to manual
Signed-off-by: Paul Spooren <mail@aparcar.org>
2024-03-01 19:12:30 +01:00
Paul Spooren
4f4e8e1018 config: drop deprecated std::env::home_dir()
Instead use the `home` create.

Signed-off-by: Paul Spooren <mail@aparcar.org>
2024-03-01 19:00:00 +01:00
Ilka Schulz
971e49b894 debug-log change in log level filter via CLI parameter 2024-02-29 13:38:54 +01:00
Ilka Schulz
262e32fe35 resolve #92: add CLI argument to specify log level filter 2024-02-29 13:38:54 +01:00
Ilka Schulz
4dab97d84e use <> brackets around hyperlinks in comments because GitHub actions complained 2024-02-29 13:37:43 +01:00
Ilka Schulz
1a5ffdd495 resolve #237: resolve paths starting with "~/" in config file 2024-02-29 13:37:43 +01:00
Ilka Schulz
fb91688672 add few comments to config.rs 2024-02-29 13:37:43 +01:00
Ilka Schulz
27ba729c14 move each primitive into its own module; add rough documentation
This commit does not change anything about the implementations.
2024-02-29 13:36:54 +01:00
Ilka Schulz
60235dc6ea GihHub Workflow "Quality Control": add flag "--all-features" to cargo in order to run all available tests behind feature flags 2024-02-28 17:07:40 +01:00
Ilka Schulz
36c99c020e implement test to statistically check constant run time of memcmp (feature: constant_time_tests) 2024-02-28 17:07:40 +01:00
James Brownlee
8c469af6b1 adding identity hiding improvements:
seperate files for responder and initiator tests
test file that shows other participants leaking info has an effect
general code clean up
performance improvement: initiator and responder tests now run in ~10s
2024-02-26 17:20:33 +01:00
James Brownlee
e96968b8bc adding dos protection code 2024-02-26 17:20:33 +01:00
Aaron Kaiser
81487b103d refactor: Get rid of comment and unessary truncation of buffer 2024-02-21 14:04:39 +01:00
Aaron Kaiser
8ea253f86b refactor: use memoffset crate instead of unstable offset_of feature 2024-02-21 14:04:39 +01:00
Aaron Kaiser
fd8f2e4424 style: apply rustfmt 2024-02-21 14:04:39 +01:00
Aaron Kaiser
a996b08279 refactor: replace lenses library with the zerocopy crate 2024-02-21 14:04:39 +01:00
Prabhpreet Dua
19a0a22b62 Cargo fmt 2024-02-18 14:13:33 +05:30
Prabhpreet Dua
b51466eaec Add intg test to pipeline 2024-02-18 14:10:49 +05:30
Prabhpreet Dua
9552d5a46c Merge branch 'main' into feat/cookie-mechanism 2024-02-18 13:25:01 +05:30
Prabhpreet Dua
a1d61bb48e Evaluate both active and retired cookies- cookie rotation 2024-02-18 13:19:22 +05:30
Emil Engler
e38a6b8ed4 Merge pull request #238 from beau2am/contribution-beau2am
Fixed grammatical typo in 'cli.rs'. To resolve issue #236.
2024-02-10 17:46:45 +01:00
Beau McDermott
639541ab4f fix: Grammatical typo in cli.rs
Fixes #236
2024-02-10 17:45:20 +01:00
Prabhpreet Dua
ec0b5f7fb1 Cargo fmt 2024-02-04 20:18:58 +05:30
Prabhpreet Dua
0b4699e24a Poll based under load with intg test 2024-02-04 20:17:28 +05:30
Prabhpreet Dua
d18107b3a9 Merge branch 'poll-based-under-load-in-progress' into feat/cookie-mechanism 2024-02-04 11:53:05 +05:30
Prabhpreet Dua
715893e1ac cargo fmt 2024-02-04 11:49:08 +05:30
Prabhpreet Dua
92b2f6bc7c Match to main 2024-02-04 11:48:49 +05:30
Prabhpreet Dua
3498ab2d7b Checkpoint 2024-02-04 11:39:34 +05:30
Karolin Varner
9690085156 chore: Cargo fmt 2024-01-27 21:38:13 +01:00
Karolin Varner
ca972e8b70 feat: Remove libsodium 2024-01-27 21:38:13 +01:00
Karolin Varner
2fa0a2a72a feat: Use core::hint::black_box in rosenpass_constant_time::xor 2024-01-27 21:38:13 +01:00
Karolin Varner
b6203683fc feat: Migrate away from sodium blake2b towards the rust crypto implementation 2024-01-27 21:38:13 +01:00
Karolin Varner
e0f75ab97e feat: Use xchacha implementation from rust crypto instead of sodium 2024-01-27 21:38:13 +01:00
Karolin Varner
0789c60602 feat: Use chacha implementation from rust crypto instead of sodium 2024-01-27 21:38:13 +01:00
Karolin Varner
e42f90b048 chore: Add helper to turn typenums into const values 2024-01-27 21:38:13 +01:00
Emil Engler
29917fd7a6 doc: Fix keygen/gen-keys misspell
Fixes #166
2024-01-21 20:54:29 +01:00
Prabhpreet Dua
efd0ce51cb On-stack allocated host identification 2024-01-21 13:53:05 +05:30
Prabhpreet Dua
7739020931 Cargo fmt 2024-01-15 19:35:08 +05:30
Prabhpreet Dua
ecfecbb8f9 Host identification 2024-01-15 18:57:16 +05:30
Prabhpreet Dua
e8a81102f4 Whitepaper updates per review comments 2024-01-07 16:59:55 +05:30
Prabhpreet Dua
591e5226fd Merge branch 'main' into feat/cookie-mechanism 2024-01-06 17:25:04 +05:30
wucke13
62aa9b4351 fix: second round of clippy lints
Clippy would not automatically apply these fixes, so they were applied
by hand.
2024-01-03 18:43:05 +01:00
wucke13
26cb4a587f fix: apply clippy lints 2024-01-03 18:43:05 +01:00
wucke13
1c14be38dd fix: make benches work again
Somehow in the past while splitting into many crates, we broke the bench
setup. This commit both fixes it, and adds a CI job that ensures it is
still working to avoid such silent failure in the future. The benchmarks
are not actually run, they would take forever on the slow GitHub Actions
runners, but they are at least compiled.
2024-01-03 18:43:05 +01:00
Karolin Varner
30cb0e9801 chore: Remove references to libsodium from secret-memory 2024-01-03 18:43:05 +01:00
Karolin Varner
9824db4f09 fix: Migrate away from lazy_static in favor of thread_local
The new secret memory pool was causing CI failures in the fuzzing code,
due to the fuzzer compiling its binaries with memory sanitizer support.

https://doc.rust-lang.org/beta/unstable-book/compiler-flags/sanitizer.html

Using lazy_static was – intentionally – introducing a memory leak, but the
LeakSanitizer detected this and raised an error.

Now by using thread_local we are calling the destructors and so – while still being a
memory leak in practice – the LeakSanitizer no longer detects this behaviour as an error.

Alternatively we could have used a known-leaks list with the leak-sanitizer, but this would have increased the complexity of the build setup.

Finally, this was likely triggered with the migration to memsec, because libsodium circumvents the malloc/free calls,
relying on direct calls to MMAP.
2024-01-03 18:43:05 +01:00
Karolin Varner
e3b72487db fix: Make sure all tests are run during CI runs
Had to fix the tests in util/src/result.rs.
2024-01-03 18:43:05 +01:00
Karolin Varner
85c447052e feat: Migrate to memsec 2024-01-03 18:43:05 +01:00
James Brownlee
b2a64ed17a feat: add INITIATOR_TEST and RESPONDER_TEST macros
Added INITIATOR_TEST and RESPONDER_TEST macros to the identity hiding
mpv file that can be used to selectively test the anonymity of the
initiator or the responder.
2024-01-03 18:35:54 +01:00
James Brownlee
91da0dfd2d feat: identity hiding in two stage process
Changed identity hiding test to work as a two stage process where
participants with fresh secure secret keys communicate with each other
and other compromised participants. Then the attacker is asked to
identify the difference between two of the secure participants as on of
them acts as a responder.
2024-01-03 18:35:54 +01:00
James Brownlee
4a170b1983 feat: add inital identity hiding code to proverif 2024-01-03 18:35:54 +01:00
wucke13
7c83e244f9 fix: fix Rust code in markdown files
This applies the novel format_rustcode.sh script to the markdown files in the
repo, to maintain a consistent style across code examples.
2023-12-22 17:57:32 +01:00
alankritdabral_2
eb76179dc4 feat: add format_rustcode.sh script
This script makes it possible to check formatting of rust code found in the various markdown files in the repo. It is also added as a job to the QC CI workflow.
2023-12-22 17:57:32 +01:00
wucke13
d84efa7422 Merge pull request #197 from guhitb/main
Add backwards compatibility for keygen command
2023-12-21 11:28:25 +01:00
user
61ef5b92bb fix: add deprecated keygen command
This allows users to use the old keygen command, while being informed
about its deprecation.
2023-12-20 16:03:47 +01:00
Prabhpreet Dua
b336a0d264 Separate cookie message from envelope encapsulation, remove mac, cookie field 2023-12-12 07:24:08 +05:30
Prabhpreet Dua
0b7bec75de Use common CookieStore for biscuit, and cookie secret, add padding to CookieReply, trigger immediate retransmission on recieving cookie reply 2023-12-10 18:17:37 +05:30
Prabhpreet Dua
87bbd1eef7 Reuse lifecycle (biscuit mechanism) for cookie expiration 2023-12-10 17:10:12 +05:30
Prabhpreet Dua
2646dc8398 Further updates to whitepaper 2023-12-08 00:13:55 +05:30
Prabhpreet Dua
4295ec9d80 Whitepaper changes, and reflect in code 2023-12-07 23:59:40 +05:30
Prabhpreet Dua
7cb643b181 app_server move under load handling to function, cargo fmt 2023-12-07 22:53:17 +05:30
Prabhpreet Dua
109d624227 SID specific cookie storage 2023-12-07 20:19:57 +05:30
Prabhpreet Dua
b96d195f54 Avoid memory allocations ctd 2023-12-06 23:02:57 +05:30
Prabhpreet Dua
775b464496 Remove debug message 2023-12-06 22:32:35 +05:30
Prabhpreet Dua
e2cd25c184 Use retransmitted message instead of storing last sent mac 2023-12-06 21:59:52 +05:30
Prabhpreet Dua
fdcb488d4b Move IP+Port into AppServer from protocol.rs 2023-12-06 21:28:21 +05:30
Prabhpreet Dua
a8a596ca7e Remove debug messages 2023-12-06 05:40:34 +05:30
Prabhpreet Dua
9ced9996d2 Remove serial_test deps 2023-12-05 06:40:35 +05:30
Prabhpreet Dua
df683f96b2 Remove ignore from second test, init libsodium in that test too 2023-12-05 06:30:59 +05:30
Prabhpreet Dua
27a8bdbe7b Init libsodium in failing test 2023-12-05 06:26:41 +05:30
Prabhpreet Dua
bdabae9c33 Remove ignore for one test 2023-12-05 06:20:01 +05:30
Prabhpreet Dua
4d7c030476 Ignore existing tests 2023-12-05 06:15:19 +05:30
Prabhpreet Dua
95f22e98ac Try all tests running in serial for protocol 2023-12-05 06:08:59 +05:30
Prabhpreet Dua
b0dada7613 cargo fmt run 2023-12-05 06:00:11 +05:30
Prabhpreet Dua
e54ea1feaa Add parallel test flag, and remove .orig files 2023-12-05 05:58:13 +05:30
Prabhpreet Dua
0fd09c908b Merge branch 'main' into feat/cookie-mechanism 2023-12-03 21:06:14 +05:30
Prabhpreet Dua
36628a46d6 Serial test execution for cookie exchange 2023-12-03 20:54:26 +05:30
wucke13
184cff0e5e Merge pull request #196 from rosenpass/dev/fix-65
fix: remove OSFONTDIR var from whitepaper build
2023-12-03 14:01:25 +01:00
wucke13
9819148b6f fix: remove OSFONTDIR var from whitepaper build
Fixes #65. I checked with `pdffonts` that the whitepaper still has all fonts embedded.
2023-12-03 13:27:47 +01:00
Prabhpreet Dua
2904c90d4b Cargo fmt 2023-12-02 19:38:10 +05:30
Prabhpreet Dua
f0dbe2bb54 Merge branch 'main' into feat/cookie-mechanism 2023-12-02 19:36:04 +05:30
Morgan Hill
3a0ebd2cbc feat: Add fuzzing for libsodium allocator 2023-12-02 14:14:05 +01:00
Karolin Varner
1eefb5f263 fix: Guaranteed results typo 2023-12-02 12:21:41 +01:00
Karolin Varner
d45e24e9b6 feat: Move lenses into library 2023-12-02 12:21:41 +01:00
Karolin Varner
972e82b35f chore: Move kems out of rosenpass crate 2023-12-02 10:42:13 +01:00
Karolin Varner
101c9bf4b3 feat: Add an internal library for guaranteed results
This is helpful for functions that have to return a result to
implement some interface but that do not actually need to return
a result value.
2023-12-02 10:42:13 +01:00
Marei (peiTeX)
955d57ea49 fix output of authorlist to support unlimited authors 2023-12-01 20:25:58 +01:00
Karolin Varner
838f700a74 chore: Upgrade dependencies 2023-12-01 18:43:32 +01:00
Karolin Varner
5448cdc565 feat: Use the rand crate for random values instead of sodium 2023-12-01 18:37:33 +01:00
Karolin Varner
77cd8a9fd1 feat: Move prftree into ciphers crate
- Use a new nomenclature for these functions based on the idea of a hash
  domain (as in domain separation); this makes much more sence
- Remove the ciphers::hash export; we did not even export a hash
  function in the purest sence of the word. This gets us around the
  difficulty of figuring out what we should call the underlying
  primitive
2023-12-01 18:36:46 +01:00
Karolin Varner
0f89ab7976 chore: Shorten fuzzing runtime to make sure the CI finishes quickly 2023-12-01 18:30:16 +01:00
Karolin Varner
70fa9bd6d7 feat: Wrap sodium_malloc as a custom allocator
This lets us get rid of quite a few unsafe blocks.
2023-12-01 18:29:53 +01:00
Karolin Varner
85a61808de feat: Use the zeroize crate for zeroization 2023-12-01 18:11:05 +01:00
Karolin Varner
cf132bca11 chore: Move rest of coloring.rs into secret-memory crate
Also removes the StoreSecret trait from cli.rs as it was
redundant.
2023-12-01 18:11:05 +01:00
Karolin Varner
7bda010a9b chore: Move Public and debug_crypto_array into secret-memory crate 2023-12-01 18:11:05 +01:00
Olaf Pichler
36089fd37f Added example for additional PSK 2023-12-01 15:44:42 +01:00
Olaf Pichler
31d43accd5 #172 removed exchange_command 2023-12-01 15:44:42 +01:00
Olaf Pichler
205c301012 Added indications that file paths are used 2023-12-01 15:44:42 +01:00
Olaf Pichler
d014095469 Added indication that exchange_command is not used 2023-12-01 15:44:42 +01:00
Olaf Pichler
7cece82119 added WireGuard config example to gen-config 2023-12-01 15:44:42 +01:00
Ezhil Shanmugham
284ebb261f fix: enabled fuzzing 2023-12-01 11:43:37 +01:00
Jemilu Mohammed
ba224a2200 add default member
add shared dependencies to workspace dependencies

all package level dependencies now rely on workspace
2023-11-30 18:44:28 +01:00
Jemilu Mohammed
ca35e47d2a manage features in workspaces cargo.toml file 2023-11-30 18:44:28 +01:00
Jemilu Mohammed
181154b470 move external dependencies to workspace level 2023-11-30 18:44:28 +01:00
Karolin Varner
cc8c13e121 chore: Remove lprf.rs (dead code) 2023-11-30 11:26:24 +01:00
Prabhpreet Dua
e2792272e8 Merge branch 'main' into feat/cookie-mechanism 2023-11-29 21:01:32 +05:30
Karolin Varner
40861cc2ea fix: Nix flake failing due to rosenpass-to
README.md was missing; added it to the list of source files
2023-11-29 11:36:28 +01:00
Karolin Varner
09aa0e027e chore: Move hashing functions into sodium/ciphers crate
This finishes the last step of removing sodium.rs from the rosenpass crate
itself and also removes the NOTHING and NONCE0 constants.

Hashing functions now use destination parameters;
rosenpass_constant_time::xor now does too.
2023-11-29 11:36:28 +01:00
Morgan Hill
d44793e07f Remove unwrap from fuzz targets that return errors
When fuzzing we are interested in what happens inside the target function
not necessarily what it returns. Functions returning errors with bogus
input in generally desired behaviour.
2023-11-29 11:36:07 +01:00
Prabhpreet Dua
1c65e67be2 Fix cargo fmt lint 2023-11-29 05:10:18 +05:30
Prabhpreet Dua
2ae3d6c271 Merge branch 'main' into feat/cookie-mechanism, ignore incoming messages when initiator is under load, whitepaper updates 2023-11-29 05:06:22 +05:30
Karolin Varner
d539be3142 feat: Rosenpass-to for nicely handling destination parameters 2023-11-26 11:18:47 +01:00
Morgan Hill
a49254a021 feat(fuzzing): Add initial set of fuzzing targets
These targets can be used with rust nightly and cargo-fuzz to fuzz
several bits of Rosenpass's API. Fuzzing is an automated way of
exploring code paths that may not be hit in unit tests or normal
operation. For example the `handle_msg` target exposed the DoS condition
fixed in 0.2.1.

The other targets focus on the FFI with libsodium and liboqs.

Co-authored-by: Karolin Varner <karo@cupdev.net>
2023-11-26 11:05:19 +01:00
Karolin Varner
86300ca936 chore: Use naming scheme without rosenpass- for crates 2023-11-26 10:38:24 +01:00
Karolin Varner
3ddf736b60 chore: Move xchacha20 implementation out of rosenpass::sodium 2023-11-26 10:38:24 +01:00
Karolin Varner
c64e721c2f chore: Move chacha20 implementation out of rosenpass::sodium
Introduces a new crate for selected ciphers which references
a cipher implementation in the rosenpass-sodium crate.
2023-11-26 10:38:24 +01:00
Karolin Varner
4c51ead078 chore: Move libsodium's helper function into their own namespace 2023-11-26 10:38:24 +01:00
Karolin Varner
c5c34523f3 chore: Move libsodium's memzero, randombytes fns into rosenpass-sodium 2023-11-26 10:38:24 +01:00
Karolin Varner
6553141637 chore: Move libsodium's increment into rosenpass-sodium crate 2023-11-26 10:38:24 +01:00
Karolin Varner
a3de526db8 chore: Move libsodium's compare into rosenpass-sodium crate 2023-11-26 10:38:24 +01:00
Karolin Varner
5da0e4115e chore: Move memcmp into rosenpass-sodium crate 2023-11-26 10:38:24 +01:00
Karolin Varner
99634d9702 chore: Move sodium init integration into rosenpass-sodium crate 2023-11-26 10:38:24 +01:00
Karolin Varner
46156fcb29 fix: Setup cargo fmt to check the entire workspace 2023-11-26 10:38:24 +01:00
Karolin Varner
e50542193f chore: Move file utils into coloring or the util crate 2023-11-26 10:38:24 +01:00
Karolin Varner
3db9755580 chore: move functional utils into utils library 2023-11-26 10:38:24 +01:00
Karolin Varner
556dbd2600 chore: move time utils into util crate 2023-11-26 10:38:24 +01:00
Karolin Varner
6cd42ebf50 chore: move max_usize into util crate 2023-11-26 10:38:24 +01:00
Karolin Varner
a220c11e67 chore: Move xor_into, copying and base64 utils into own crates 2023-11-26 10:38:24 +01:00
Emil Engler
c9cef05b29 doc: Add bibliography to the manual page
Fixes #153
2023-11-26 09:51:11 +01:00
Prabhpreet Dua
96d4f0b545 Merge branch 'main' into feat/cookie-mechanism 2023-11-19 12:06:33 +05:30
Prabhpreet Dua
ad947a755c Add test with initiator under load, add section to WP 2023-11-19 11:30:12 +05:30
wucke13
0b4b1279cf chore: Release rosenpass version 0.2.1 2023-11-18 23:16:22 +01:00
wucke13
44264a7bb6 chore: Release rosenpass version 0.2.1-rc.3 2023-11-18 22:58:57 +01:00
wucke13
b095bdaa7c refine ab085998bb
This commit refines the above by making cargo release emit no prefix for release tags even if only a single package is released.
2023-11-18 22:57:53 +01:00
wucke13
9597e485bf chore: Release rosenpass version 0.2.1-rc.2 2023-11-18 22:48:35 +01:00
wucke13
ab085998bb add new trigger for release workflow
The change to a multi crate cargo workspace makes `cargo release` behave differently. Now it prefixes the release tags (e.g. `v0.2.0`) with the package name, so for example `rosenpass-v0.2.0`. This change adds the
2023-11-18 22:43:47 +01:00
wucke13
3901e668cb chore: Release rosenpass version 0.2.1-rc.1 2023-11-18 22:30:46 +01:00
wucke13
b7444bf9b4 add readme link to rosenpass package 2023-11-18 22:25:05 +01:00
Benjamin Lipp
0051cbd48e doc: Add unit test for xor_into 2023-11-15 14:32:19 +01:00
Prabhpreet Dua
35f9c3bf68 Cookie reply processing continued 2023-11-14 21:42:48 +05:30
Prabhpreet Dua
ff44002b7c Cookie reply handler test setup 2023-11-13 20:57:34 +05:30
Prabhpreet Dua
0ce8304c69 Merge branch 'main' into feat/cookie-mechanism 2023-11-13 14:55:10 +05:30
Prabhpreet Dua
5f91feb3a4 Checkpoint- cookie reply handler 2023-11-13 14:47:39 +05:30
Karolin Varner
27746781c0 fix: Doctest should pass buffers of correct length to handle_msg 2023-11-12 14:42:23 +01:00
Karolin Varner
93439858d1 fix crash on undersized buffers going through the lenses
Co-authored-by: wucke13 <wucke13@gmail.com>
2023-11-12 14:42:23 +01:00
wucke13
1223048b48 Merge pull request #148 from rosenpass/dev/wucke13-update-lock-files
update lock files
2023-11-12 13:44:10 +01:00
wucke13
932bde39cc flake.lock: Update
Flake lock file updates:

• Updated input 'fenix':
    'github:nix-community/fenix/add522038f2a32aa1263c8d3c81e1ea2265cc4e1' (2023-08-23)
  → 'github:nix-community/fenix/81ab0b4f7ae9ebb57daa0edf119c4891806e4d3a' (2023-11-12)
• Updated input 'fenix/rust-analyzer-src':
    'github:rust-lang/rust-analyzer/9e3bf69ad3c736893b285f47f4d014ae1aed1cb0' (2023-08-22)
  → 'github:rust-lang/rust-analyzer/5fcf5289e726785d20d3aa4d13d90a43ed248e83' (2023-11-11)
• Updated input 'flake-utils':
    'github:numtide/flake-utils/919d646de7be200f3bf08cb76ae1f09402b6f9b4' (2023-07-11)
  → 'github:numtide/flake-utils/ff7b65b44d01cf9ba6a71320833626af21126384' (2023-09-12)
• Updated input 'naersk':
    'github:nix-community/naersk/78789c30d64dea2396c9da516bbcc8db3a475207' (2023-08-18)
  → 'github:nix-community/naersk/aeb58d5e8faead8980a807c840232697982d47b9' (2023-10-27)
• Updated input 'nixpkgs':
    'github:NixOS/nixpkgs/78287547942dd8e8afff0ae47fb8e2553db79d7e' (2023-08-08)
  → 'github:NixOS/nixpkgs/34bdaaf1f0b7fb6d9091472edc968ff10a8c2857' (2023-11-01)
2023-11-12 13:29:22 +01:00
wucke13
1d9e62e56b update Cargo.lock 2023-11-12 13:29:06 +01:00
wucke13
3af722a066 Merge pull request #143 from rosenpass/dev/refactor-rp-to-workspace
refactor rp to workspace
2023-11-12 13:27:31 +01:00
wucke13
df60b0bfc3 refine source filter
In particular, replace the error prone sourceByRegex filter for the rosenpass derivation with a simple file suffix filter.
2023-11-12 13:16:34 +01:00
wucke13
6274c6fcdd add workspace Cargo.toml 2023-11-12 13:16:34 +01:00
wucke13
cd00f023fb move the current rosenpass codebase into a subdir
This is preparation to make the rosenpass repo a workspace, which can contain multiple crates.
2023-11-12 13:16:34 +01:00
Prabhpreet Dua
baebb8632f Merge branch 'main' into feat/cookie-mechanism 2023-11-09 19:33:35 +05:30
Prabhpreet Dua
cb97f90581 cookie mechanism trigger- send cookie reply message under load if cookie not valid 2023-11-09 19:28:02 +05:30
Karolin Varner
13563237cb chore: rustfmt 2023-11-08 22:05:30 +01:00
Karolin Varner
447a4f7a44 fix: Restore benchmarks to working order 2023-11-08 22:05:30 +01:00
Prabhpreet Dua
3d13caa37b cookie mechanism trigger- under load condition and mio event length 2023-11-07 20:49:43 +05:30
Prabhpreet Dua
54ecfaddcf Whitepaper- add cookie mechanism description draft 2023-10-25 01:43:08 +05:30
wucke13
6bac6a59ff Merge pull request #141 from rosenpass/dev/engler/app_server
app_server: Replace `is_ok()` by `if let`
2023-10-19 23:09:05 +02:00
Emil Engler
e5e04c6d95 app_server: Replace is_ok() by if let
This commit replaces an `is_ok()` call with a call to `if let`, thereby
fixing a clippy warning.
2023-10-19 13:54:13 +02:00
Emil Engler
15ce25ccd2 Merge pull request #140 from rosenpass/AliceOrunitia-patch-1
Update rosenpass.1
2023-10-19 13:51:28 +02:00
Alice Michaela Bowman
1b383d494c Update rosenpass.1
Small grammatical changes.
2023-10-19 12:44:56 +02:00
Emil Engler
605b6463ff Merge pull request #134 from rosenpass/dev/engler/stack
Follow-ups to the stack increasements
2023-10-06 10:55:14 +02:00
Ashish SHUKLA
04eb86af87 cli: move wg exit status check to thread 2023-10-06 08:27:43 +02:00
Ashish SHUKLA
bf850e3072 cli: handle the exit status of wg process 2023-10-06 08:27:43 +02:00
Ashish SHUKLA
dd39936220 cli: reap spawned wireguard child
Fixes #132
2023-10-06 08:27:43 +02:00
wucke13
b15f17133f Merge pull request #135 from lorenzleutgeb/patch-1
config: Default `WireGuard::extra_params` to empty `Vec`
2023-09-28 19:59:15 +02:00
Lorenz Leutgeb
b50820ecc0 config: Default WireGuard::extra_params to empty Vec
Otherwise, omitting `extra_params` in the configuration file will result in a `WireGuard` configuration object of `None`, even though not specifying `extra_params` is sane.
2023-09-28 11:16:38 +02:00
Emil Engler
f323839967 test: Fix wrong comment
This commit fixes a wrong comment, claiming that the unit tests uses a
stack size of 16MB, where in fact it only uses 8MiB.
2023-09-28 07:58:17 +02:00
Emil Engler
6e15c38254 flake: Remove redundant stack increase
This commit removes the setting of `RUST_MIN_STACK` by the Nix
development shell, because the tests now set the stack size on their
own.

See #128
2023-10-06 10:43:41 +02:00
198 changed files with 20978 additions and 4464 deletions

View File

@@ -1,6 +1,6 @@
#!/usr/bin/env nu
use log *
use std log
# cd to git root
cd (git rev-parse --show-toplevel)
@@ -116,6 +116,7 @@ for system in ($targets | columns) {
} }
| filter {|it| $it.needed}
| each {|it| job-id $system $it.name}
| sort
)
mut new_job = {
@@ -197,4 +198,4 @@ $cachix_workflow | to yaml | save --force .github/workflows/nix.yaml
$release_workflow | to yaml | save --force .github/workflows/release.yaml
log info "prettify generated yaml"
prettier -w .github/workflows/
prettier -w .github/workflows/

33
.ci/run-regression.sh Executable file
View File

@@ -0,0 +1,33 @@
#!/usr/bin/env bash
iterations="$1"
sleep_time="$2"
PWD="$(pwd)"
EXEC="$PWD/target/release/rosenpass"
LOGS="$PWD/output/logs"
mkdir -p "$LOGS"
run_command() {
local file=$1
local log_file="$2"
("$EXEC" exchange-config "$file" 2>&1 | tee -a "$log_file") &
echo $!
}
pids=()
(cd output/dut && run_command "configs/dut-$iterations.toml" "$LOGS/dut.log")
for (( x=0; x<iterations; x++ )); do
(cd output/ate && run_command "configs/ate-$x.toml" "$LOGS/ate-$x.log") & pids+=($!)
done
sleep "$sleep_time"
lsof -i :9999 | awk 'NR!=1 {print $2}' | xargs kill
for (( x=0; x<iterations; x++ )); do
port=$((x + 50000))
lsof -i :$port | awk 'NR!=1 {print $2}' | xargs kill
done

1
.devcontainer/Dockerfile Normal file
View File

@@ -0,0 +1 @@
FROM ghcr.io/xtruder/nix-devcontainer:v1

View File

@@ -0,0 +1,33 @@
// For format details, see https://aka.ms/vscode-remote/devcontainer.json or the definition README at
// https://github.com/microsoft/vscode-dev-containers/tree/master/containers/docker-existing-dockerfile
{
"name": "devcontainer-project",
"dockerFile": "Dockerfile",
"context": "${localWorkspaceFolder}",
"build": {
"args": {
"USER_UID": "${localEnv:USER_UID}",
"USER_GID": "${localEnv:USER_GID}"
}
},
// run arguments passed to docker
"runArgs": ["--security-opt", "label=disable"],
// disable command overriding and updating remote user ID
"overrideCommand": false,
"userEnvProbe": "loginShell",
"updateRemoteUserUID": false,
// build development environment on creation, make sure you already have shell.nix
"onCreateCommand": "nix develop",
// Use 'forwardPorts' to make a list of ports inside the container available locally.
"forwardPorts": [],
"customizations": {
"vscode": {
"extensions": ["rust-lang.rust-analyzer", "tamasfe.even-better-toml"]
}
}
}

14
.github/codecov.yml vendored Normal file
View File

@@ -0,0 +1,14 @@
codecov:
branch: main
coverage:
status:
project:
default:
# basic
target: auto #default
threshold: 5
base: auto
if_ci_failed: error #success, failure, error, ignore
informational: false
only_pulls: true
patch: off

6
.github/dependabot.yml vendored Normal file
View File

@@ -0,0 +1,6 @@
version: 2
updates:
- package-ecosystem: "cargo"
directory: "/"
schedule:
interval: "daily"

63
.github/workflows/dependent-issues.yml vendored Normal file
View File

@@ -0,0 +1,63 @@
name: Dependent Issues
on:
issues:
types:
- opened
- edited
- closed
- reopened
pull_request_target:
types:
- opened
- edited
- closed
- reopened
# Makes sure we always add status check for PRs. Useful only if
# this action is required to pass before merging. Otherwise, it
# can be removed.
- synchronize
# Schedule a daily check. Useful if you reference cross-repository
# issues or pull requests. Otherwise, it can be removed.
schedule:
- cron: "0 0 * * *"
jobs:
check:
permissions:
issues: write
pull-requests: write
statuses: write
runs-on: ubuntu-latest
steps:
- uses: z0al/dependent-issues@v1
env:
# (Required) The token to use to make API calls to GitHub.
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
# (Optional) The token to use to make API calls to GitHub for remote repos.
GITHUB_READ_TOKEN: ${{ secrets.GITHUB_READ_TOKEN }}
with:
# (Optional) The label to use to mark dependent issues
label: dependent
# (Optional) Enable checking for dependencies in issues.
# Enable by setting the value to "on". Default "off"
check_issues: off
# (Optional) Ignore dependabot PRs.
# Enable by setting the value to "on". Default "off"
ignore_dependabot: off
# (Optional) A comma-separated list of keywords. Default
# "depends on, blocked by"
keywords: depends on, blocked by
# (Optional) A custom comment body. It supports `{{ dependencies }}` token.
comment: >
This PR/issue depends on:
{{ dependencies }}
By **[Dependent Issues](https://github.com/z0al/dependent-issues)** (🤖). Happy coding!

View File

@@ -6,6 +6,11 @@ on:
push:
branches:
- main
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
jobs:
i686-linux---default:
name: Build i686-linux.default
@@ -95,6 +100,7 @@ jobs:
- macos-13
needs:
- x86_64-darwin---rosenpass
- x86_64-darwin---rp
- x86_64-darwin---rosenpass-oci-image
steps:
- uses: actions/checkout@v3
@@ -123,6 +129,22 @@ jobs:
authToken: ${{ secrets.CACHIX_AUTH_TOKEN }}
- name: Build
run: nix build .#packages.x86_64-darwin.rosenpass --print-build-logs
x86_64-darwin---rp:
name: Build x86_64-darwin.rp
runs-on:
- macos-13
needs: []
steps:
- uses: actions/checkout@v3
- uses: cachix/install-nix-action@v22
with:
nix_path: nixpkgs=channel:nixos-unstable
- uses: cachix/cachix-action@v12
with:
name: rosenpass
authToken: ${{ secrets.CACHIX_AUTH_TOKEN }}
- name: Build
run: nix build .#packages.x86_64-darwin.rp --print-build-logs
x86_64-darwin---rosenpass-oci-image:
name: Build x86_64-darwin.rosenpass-oci-image
runs-on:
@@ -210,8 +232,9 @@ jobs:
runs-on:
- ubuntu-latest
needs:
- x86_64-linux---rosenpass-static-oci-image
- x86_64-linux---rosenpass-static
- x86_64-linux---rosenpass-static-oci-image
- x86_64-linux---rp-static
steps:
- uses: actions/checkout@v3
- uses: cachix/install-nix-action@v22
@@ -223,6 +246,30 @@ jobs:
authToken: ${{ secrets.CACHIX_AUTH_TOKEN }}
- name: Build
run: nix build .#packages.x86_64-linux.release-package --print-build-logs
# aarch64-linux---release-package:
# name: Build aarch64-linux.release-package
# runs-on:
# - ubuntu-latest
# needs:
# - aarch64-linux---rosenpass-oci-image
# - aarch64-linux---rosenpass
# - aarch64-linux---rp
# steps:
# - run: |
# DEBIAN_FRONTEND=noninteractive
# sudo apt-get update -q -y && sudo apt-get install -q -y qemu-system-aarch64 qemu-efi binfmt-support qemu-user-static
# - uses: actions/checkout@v3
# - uses: cachix/install-nix-action@v22
# with:
# nix_path: nixpkgs=channel:nixos-unstable
# extra_nix_config: |
# system = aarch64-linux
# - uses: cachix/cachix-action@v12
# with:
# name: rosenpass
# authToken: ${{ secrets.CACHIX_AUTH_TOKEN }}
# - name: Build
# run: nix build .#packages.aarch64-linux.release-package --print-build-logs
x86_64-linux---rosenpass:
name: Build x86_64-linux.rosenpass
runs-on:
@@ -239,6 +286,48 @@ jobs:
authToken: ${{ secrets.CACHIX_AUTH_TOKEN }}
- name: Build
run: nix build .#packages.x86_64-linux.rosenpass --print-build-logs
aarch64-linux---rosenpass:
name: Build aarch64-linux.rosenpass
runs-on:
- ubuntu-latest
needs: []
steps:
- run: |
DEBIAN_FRONTEND=noninteractive
sudo apt-get update -q -y && sudo apt-get install -q -y qemu-system-aarch64 qemu-efi binfmt-support qemu-user-static
- uses: actions/checkout@v3
- uses: cachix/install-nix-action@v22
with:
nix_path: nixpkgs=channel:nixos-unstable
extra_nix_config: |
system = aarch64-linux
- uses: cachix/cachix-action@v12
with:
name: rosenpass
authToken: ${{ secrets.CACHIX_AUTH_TOKEN }}
- name: Build
run: nix build .#packages.aarch64-linux.rosenpass --print-build-logs
aarch64-linux---rp:
name: Build aarch64-linux.rp
runs-on:
- ubuntu-latest
needs: []
steps:
- run: |
DEBIAN_FRONTEND=noninteractive
sudo apt-get update -q -y && sudo apt-get install -q -y qemu-system-aarch64 qemu-efi binfmt-support qemu-user-static
- uses: actions/checkout@v3
- uses: cachix/install-nix-action@v22
with:
nix_path: nixpkgs=channel:nixos-unstable
extra_nix_config: |
system = aarch64-linux
- uses: cachix/cachix-action@v12
with:
name: rosenpass
authToken: ${{ secrets.CACHIX_AUTH_TOKEN }}
- name: Build
run: nix build .#packages.aarch64-linux.rp --print-build-logs
x86_64-linux---rosenpass-oci-image:
name: Build x86_64-linux.rosenpass-oci-image
runs-on:
@@ -256,6 +345,28 @@ jobs:
authToken: ${{ secrets.CACHIX_AUTH_TOKEN }}
- name: Build
run: nix build .#packages.x86_64-linux.rosenpass-oci-image --print-build-logs
aarch64-linux---rosenpass-oci-image:
name: Build aarch64-linux.rosenpass-oci-image
runs-on:
- ubuntu-latest
needs:
- aarch64-linux---rosenpass
steps:
- run: |
DEBIAN_FRONTEND=noninteractive
sudo apt-get update -q -y && sudo apt-get install -q -y qemu-system-aarch64 qemu-efi binfmt-support qemu-user-static
- uses: actions/checkout@v3
- uses: cachix/install-nix-action@v22
with:
nix_path: nixpkgs=channel:nixos-unstable
extra_nix_config: |
system = aarch64-linux
- uses: cachix/cachix-action@v12
with:
name: rosenpass
authToken: ${{ secrets.CACHIX_AUTH_TOKEN }}
- name: Build
run: nix build .#packages.aarch64-linux.rosenpass-oci-image --print-build-logs
x86_64-linux---rosenpass-static:
name: Build x86_64-linux.rosenpass-static
runs-on:
@@ -272,6 +383,22 @@ jobs:
authToken: ${{ secrets.CACHIX_AUTH_TOKEN }}
- name: Build
run: nix build .#packages.x86_64-linux.rosenpass-static --print-build-logs
x86_64-linux---rp-static:
name: Build x86_64-linux.rp-static
runs-on:
- ubuntu-latest
needs: []
steps:
- uses: actions/checkout@v3
- uses: cachix/install-nix-action@v22
with:
nix_path: nixpkgs=channel:nixos-unstable
- uses: cachix/cachix-action@v12
with:
name: rosenpass
authToken: ${{ secrets.CACHIX_AUTH_TOKEN }}
- name: Build
run: nix build .#packages.x86_64-linux.rp-static --print-build-logs
x86_64-linux---rosenpass-static-oci-image:
name: Build x86_64-linux.rosenpass-static-oci-image
runs-on:

View File

@@ -4,6 +4,10 @@ on:
push:
branches: [main]
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
permissions:
checks: write
contents: read
@@ -25,6 +29,44 @@ jobs:
- name: Run ShellCheck
uses: ludeeus/action-shellcheck@master
rustfmt:
name: Rust Format
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Run Rust Formatting Script
run: bash format_rust_code.sh --mode check
cargo-bench:
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') }}
# 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 bench --workspace --exclude rosenpass-fuzzing
mandoc:
name: mandoc
runs-on: ubuntu-latest
steps:
- name: Install mandoc
run: sudo apt-get install -y mandoc
- uses: actions/checkout@v3
- name: Check rosenpass.1
run: doc/check.sh doc/rosenpass.1
- name: Check rp.1
run: doc/check.sh doc/rp.1
cargo-audit:
runs-on: ubuntu-latest
steps:
@@ -47,8 +89,6 @@ jobs:
target/
key: ${{ runner.os }}-cargo-${{ hashFiles('**/Cargo.lock') }}
- run: rustup component add clippy
- name: Install libsodium
run: sudo apt-get install -y libsodium-dev
- uses: actions-rs/clippy-check@v1
with:
token: ${{ secrets.GITHUB_TOKEN }}
@@ -68,15 +108,18 @@ jobs:
target/
key: ${{ runner.os }}-cargo-${{ hashFiles('**/Cargo.lock') }}
- run: rustup component add clippy
- name: Install libsodium
run: sudo apt-get install -y libsodium-dev
# `--no-deps` used as a workaround for a rust compiler bug. See:
# - https://github.com/rosenpass/rosenpass/issues/62
# - https://github.com/rust-lang/rust/issues/108378
- run: RUSTDOCFLAGS="-D warnings" cargo doc --no-deps --document-private-items
cargo-test:
runs-on: ubuntu-latest
runs-on: ${{ matrix.os }}
strategy:
matrix:
os: [ubuntu-latest, macos-13]
# - ubuntu is x86-64
# - macos-13 is also x86-64 architecture
steps:
- uses: actions/checkout@v3
- uses: actions/cache@v3
@@ -88,12 +131,10 @@ jobs:
~/.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
- run: RUST_MIN_STACK=8388608 cargo test --workspace --all-features
cargo-test-nix-devshell-x86_64-linux:
runs-on:
@@ -116,4 +157,58 @@ jobs:
with:
name: rosenpass
authToken: ${{ secrets.CACHIX_AUTH_TOKEN }}
- run: nix develop --command cargo test
- run: nix develop --command cargo test --workspace --all-features
cargo-fuzz:
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 nightly toolchain
run: |
rustup toolchain install nightly
rustup default nightly
- name: Install cargo-fuzz
run: cargo install cargo-fuzz
- name: Run fuzzing
run: |
cargo fuzz run fuzz_aead_enc_into -- -max_total_time=5
cargo fuzz run fuzz_blake2b -- -max_total_time=5
cargo fuzz run fuzz_handle_msg -- -max_total_time=5
ulimit -s 8192000 && RUST_MIN_STACK=33554432000 && cargo fuzz run fuzz_kyber_encaps -- -max_total_time=5
cargo fuzz run fuzz_mceliece_encaps -- -max_total_time=5
cargo fuzz run fuzz_box_secret_alloc_malloc -- -max_total_time=5
cargo fuzz run fuzz_box_secret_alloc_memfdsec -- -max_total_time=5
cargo fuzz run fuzz_box_secret_alloc_memfdsec_mallocfb -- -max_total_time=5
cargo fuzz run fuzz_vec_secret_alloc_malloc -- -max_total_time=5
cargo fuzz run fuzz_vec_secret_alloc_memfdsec -- -max_total_time=5
cargo fuzz run fuzz_vec_secret_alloc_memfdsec_mallocfb -- -max_total_time=5
codecov:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- run: rustup component add llvm-tools-preview
- run: |
cargo install cargo-llvm-cov || true
cargo llvm-cov \
--workspace\
--all-features \
--lcov \
--output-path coverage.lcov
# If using tarapulin
#- run: cargo install cargo-tarpaulin
#- run: cargo tarpaulin --out Xml
- name: Upload coverage reports to Codecov
uses: codecov/codecov-action@v4
with:
files: ./coverage.lcov
verbose: true

25
.github/workflows/regressions.yml vendored Normal file
View File

@@ -0,0 +1,25 @@
name: Regressions
on:
pull_request:
push:
branches: [main]
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
permissions:
checks: write
contents: read
jobs:
multi-peer:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- run: cargo build --bin rosenpass --release
- run: python misc/generate_configs.py
- run: chmod +x .ci/run-regression.sh
- run: .ci/run-regression.sh 100 20
- run: |
[ $(ls -1 output/ate/out | wc -l) -eq 100 ]

5
.gitignore vendored
View File

@@ -20,3 +20,8 @@ _markdown_*
**/result
**/result-*
.direnv
# Visual studio code
.vscode
/output

1
.mailmap Normal file
View File

@@ -0,0 +1 @@
Clara Engler <cve@cve.cx> <me@emilengler.com>

View File

@@ -1,4 +1,5 @@
.direnv/
flake.lock
papers/whitepaper.md
target/
src/usage.md
target/

38
CONTRIBUTING.md Normal file
View File

@@ -0,0 +1,38 @@
**Making a new Release of Rosenpass — Cooking Recipe**
If you have to change a file, do what it takes to get the change as commit on the main branch, then **start from step 0**.
If any other issue occurs
0. Make sure you are in the root directory of the project
- `cd "$(git rev-parse --show-toplevel)"`
1. Make sure you locally checked out the head of the main branch
- `git stash --include-untracked && git checkout main && git pull`
2. Make sure all tests pass
- `cargo test`
3. Make sure the current version in `rosenpass/Cargo.toml` matches that in the [last release on GitHub](https://github.com/rosenpass/rosenpass/releases)
- Only normal releases count, release candidates and draft releases can be ignored
4. Pick the kind of release that you want to make (`major`, `minor`, `patch`, `rc`, ...)
- See `cargo release --help` for more information on the available release types
- Pick `rc` if in doubt
5. Try to release a new version
- `cargo release rc --package rosenpass`
- An issue was reported? Go fix it, start again with step 0!
6. Actually make the release
- `cargo release rc --package rosenpass --execute`
- Tentatively wait for any interactions, such as entering ssh keys etc.
- You may be asked for your ssh key multiple times!
**Frequently Asked Questions (FAQ)**
- You have untracked files, which `cargo release` complains about?
- `git stash --include-untracked`
- You cannot push to crates.io because you are not logged in?
- Follow the steps displayed in [`cargo login`](https://doc.rust-lang.org/cargo/commands/cargo-login.html)
- How is the release page added to [GitHub Releases](https://github.com/rosenpass/rosenpass/releases) itself?
- Our CI Pipeline will create the release, once `cargo release` pushed the new version tag to the repo. The new release should pop up almost immediately in [GitHub Releases](https://github.com/rosenpass/rosenpass/releases) after the [Actions/Release](https://github.com/rosenpass/rosenpass/actions/workflows/release.yaml) pipeline started.
- No new release pops up in the `Release` sidebar element on the [main page](https://github.com/rosenpass/rosenpass)
- Did you push a `rc` release? This view only shows non-draft release, but `rc` releases are considered as draft. See [Releases](https://github.com/rosenpass/rosenpass/releases) page to see all (including draft!) releases.
- The release page was created on GitHub, but there are no assets/artifacts other than the source code tar ball/zip?
- The artifacts are generated and pushed automatically to the release, but this takes some time (a couple of minutes). You can check the respective CI pipeline: [Actions/Release](https://github.com/rosenpass/rosenpass/actions/workflows/release.yaml), which should start immediately after `cargo release` pushed the new release tag to the repo. The release artifacts only are added later to the release, once all jobs in bespoke pipeline finished.
- How are the release artifacts generated, and what are they?
- The release artifacts are built using one Nix derivation per platform, `nix build .#release-package`. It contains both statically linked versions of `rosenpass` itself and OCI container images.

2243
Cargo.lock generated

File diff suppressed because it is too large Load Diff

View File

@@ -1,42 +1,90 @@
[package]
name = "rosenpass"
version = "0.2.0"
authors = ["Karolin Varner <karo@cupdev.net>", "wucke13 <wucke13@gmail.com>"]
edition = "2021"
license = "MIT OR Apache-2.0"
description = "Build post-quantum-secure VPNs with WireGuard!"
homepage = "https://rosenpass.eu/"
repository = "https://github.com/rosenpass/rosenpass"
readme = "readme.md"
[workspace]
resolver = "2"
[[bench]]
name = "handshake"
harness = false
members = [
"rosenpass",
"cipher-traits",
"ciphers",
"util",
"constant-time",
"oqs",
"to",
"fuzz",
"secret-memory",
"rp",
"wireguard-broker",
]
[dependencies]
anyhow = { version = "1.0.71", features = ["backtrace"] }
base64 = "0.21.1"
default-members = ["rosenpass", "rp", "wireguard-broker"]
[workspace.metadata.release]
# ensure that adding `--package` as argument to `cargo release` still creates version tags in the form of `vx.y.z`
tag-prefix = ""
[workspace.dependencies]
rosenpass = { path = "rosenpass" }
rosenpass-util = { path = "util" }
rosenpass-constant-time = { path = "constant-time" }
rosenpass-cipher-traits = { path = "cipher-traits" }
rosenpass-ciphers = { path = "ciphers" }
rosenpass-to = { path = "to" }
rosenpass-secret-memory = { path = "secret-memory" }
rosenpass-oqs = { path = "oqs" }
rosenpass-wireguard-broker = { path = "wireguard-broker" }
doc-comment = "0.3.3"
base64ct = { version = "1.6.0", default-features = false }
zeroize = "1.8.1"
memoffset = "0.9.1"
thiserror = "1.0.64"
paste = "1.0.15"
env_logger = "0.10.2"
toml = "0.7.8"
static_assertions = "1.1.0"
memoffset = "0.9.0"
libsodium-sys-stable = { version = "1.19.28", features = ["use-pkg-config"] }
oqs-sys = { version = "0.8", default-features = false, features = ['classic_mceliece', 'kyber'] }
lazy_static = "1.4.0"
thiserror = "1.0.40"
paste = "1.0.12"
log = { version = "0.4.17", optional = true }
env_logger = { version = "0.10.0", optional = true }
serde = { version = "1.0.163", features = ["derive"] }
toml = "0.7.4"
clap = { version = "4.3.0", features = ["derive"] }
mio = { version = "0.8.6", features = ["net", "os-poll"] }
allocator-api2 = "0.2.14"
memsec = { git = "https://github.com/rosenpass/memsec.git", rev = "aceb9baee8aec6844125bd6612f92e9a281373df", features = [
"alloc_ext",
] }
rand = "0.8.5"
typenum = "1.17.0"
log = { version = "0.4.22" }
clap = { version = "4.5.19", features = ["derive"] }
serde = { version = "1.0.210", features = ["derive"] }
arbitrary = { version = "1.3.2", features = ["derive"] }
anyhow = { version = "1.0.89", features = ["backtrace", "std"] }
mio = { version = "1.0.2", features = ["net", "os-poll"] }
oqs-sys = { version = "0.9.1", default-features = false, features = [
'classic_mceliece',
'kyber',
] }
blake2 = "0.10.6"
chacha20poly1305 = { version = "0.10.1", default-features = false, features = [
"std",
"heapless",
] }
zerocopy = { version = "0.7.35", features = ["derive"] }
home = "0.5.9"
derive_builder = "0.20.1"
tokio = { version = "1.40", features = ["macros", "rt-multi-thread"] }
postcard = { version = "1.0.10", features = ["alloc"] }
libcrux = { version = "0.0.2-pre.2" }
hex-literal = { version = "0.4.1" }
hex = { version = "0.4.3" }
heck = { version = "0.5.0" }
libc = { version = "0.2" }
uds = { git = "https://github.com/rosenpass/uds" }
[build-dependencies]
anyhow = "1.0.71"
[dev-dependencies]
criterion = "0.4.0"
#Dev dependencies
serial_test = "3.1.1"
tempfile = "3"
stacker = "0.1.17"
libfuzzer-sys = "0.4"
test_bin = "0.4.0"
stacker = "0.1.15"
criterion = "0.4.0"
allocator-api2-tests = "0.2.15"
procspawn = { version = "1.0.1", features = ["test-support"] }
[features]
default = ["log", "env_logger"]
#Broker dependencies (might need cleanup or changes)
wireguard-uapi = { version = "3.0.0", features = ["xplatform"] }
command-fds = "0.2.3"
rustix = { version = "0.38.37", features = ["net", "fs"] }

View File

@@ -0,0 +1,25 @@
#define INITIATOR_TEST 1
#include "rosenpass/03_identity_hiding.mpv"
// nounif a:Atom, s:seed, a2:Atom;
// ConsumeSeed(a, s, a2) / 6300[conclusion].
nounif v:seed_prec; attacker(prepare_seed(trusted_seed( v )))/6217[hypothesis].
nounif v:seed; attacker(prepare_seed( v ))/6216[hypothesis].
nounif v:seed; attacker(rng_kem_sk( v ))/6215[hypothesis].
nounif v:seed; attacker(rng_key( v ))/6214[hypothesis].
nounif v:key_prec; attacker(prepare_key(trusted_key( v )))/6213[hypothesis].
nounif v:kem_sk_prec; attacker(prepare_kem_sk(trusted_kem_sk( v )))/6212[hypothesis].
nounif v:key; attacker(prepare_key( v ))/6211[hypothesis].
nounif v:kem_sk; attacker(prepare_kem_sk( v ))/6210[hypothesis].
nounif Spk:kem_sk_tmpl;
attacker(Creveal_kem_pk(Spk))/6110[conclusion].
nounif sid:SessionId, Ssskm:kem_sk_tmpl, Spsk:key_tmpl, Sspkt:kem_sk_tmpl, Seski:seed_tmpl, Ssptr:seed_tmpl;
attacker(Cinitiator( *sid, *Ssskm, *Spsk, *Sspkt, *Seski, *Ssptr ))/6109[conclusion].
nounif sid:SessionId, biscuit_no:Atom, Ssskm:kem_sk_tmpl, Spsk:key_tmpl, Sspkt:kem_sk_tmpl, Septi:seed_tmpl, Sspti:seed_tmpl, ih:InitHello_t;
attacker(Cinit_hello( *sid, *biscuit_no, *Ssskm, *Spsk, *Sspkt, *Septi, *Sspti, *ih ))/6108[conclusion].
nounif rh:RespHello_t;
attacker(Cresp_hello( *rh ))/6107[conclusion].
nounif Ssskm:kem_sk_tmpl, Spsk:key_tmpl, Sspkt:kem_sk_tmpl, ic:InitConf_t;
attacker(Cinit_conf( *Ssskm, *Spsk, *Sspkt, *ic ))/6106[conclusion].

View File

@@ -0,0 +1,96 @@
#define RESPONDER_TEST 1
#include "rosenpass/03_identity_hiding.mpv"
// select k:kem_pk,ih: InitHello_t; attacker(prf(prf(prf(prf(key0, PROTOCOL), MAC), kem_pk2b(k) ), IH2b(ih))) phase 1/6300[hypothesis].
// select epki:kem_pk, sctr:bits, pidiC:bits, auth:bits, epki2:kem_pk, sctr2:bits, pidiC2:bits, auth2:bits;
// mess(D, prf(prf(prf(prf(key0,PROTOCOL),MAC),kem_pk2b(kem_pub(trusted_kem_sk(responder1)))),
// IH2b(InitHello(secure_sidi, *epki, *sctr, *pidiC, *auth)))
// ) [hypothesis, conclusion].
// select epki:kem_pk, sctr:bits, pidiC:bits, auth:bits, epki2:kem_pk, sctr2:bits, pidiC2:bits, auth2:bits;
// attacker(choice[prf(prf(prf(prf(key0,PROTOCOL),MAC),kem_pk2b(kem_pub(trusted_kem_sk(responder1)))),
// IH2b(InitHello(secure_sidi, *epki, *sctr, *pidiC, *auth))),
// prf(prf(prf(prf(key0,PROTOCOL),MAC),kem_pk2b(kem_pub(trusted_kem_sk(responder2)))),
// IH2b(InitHello(secure_sidi, *epki2, *sctr2, *pidiC2, *auth2)))]
// ) [hypothesis, conclusion].
// select
// attacker(prf(prf(key0,PROTOCOL),MAC)) [hypothesis, conclusion].
// select
// attacker(prf(key0,PROTOCOL)) [conclusion].
// select
// attacker(key0) [conclusion].
// select
// attacker(PROTOCOL) [conclusion].
// select
// attacker(kem_pub(trusted_kem_sk(responder1))) /9999 [hypothesis, conclusion].
// select
// attacker(kem_pub(trusted_kem_sk(responder2))) /9999 [hypothesis, conclusion].
// nounif ih:InitHello_t;
// attacker(ih) / 9999 [hypothesis].
// nounif rh:RespHello_t;
// attacker(rh) / 9999 [hypothesis].
// nounif ic:InitConf_t;
// attacker(ic) / 9999 [hypothesis].
// nounif k:key;
// attacker(ck_hs_enc( *k )) [hypothesis, conclusion].
// nounif k:key;
// attacker(ck_hs_enc( *k )) phase 1 [hypothesis, conclusion].
// nounif k:key, b:bits;
// attacker(ck_mix( *k , *b )) [hypothesis, conclusion].
// nounif k:key, b:bits;
// attacker(ck_mix( *k , *b ))phase 1 [hypothesis, conclusion].
// // select k:kem_pk, epki2:kem_pk, sctr2:bits, pidiC2:bits, auth2:bits, epki:kem_pk, sctr:bits, pidiC:bits, auth:bits;
// // attacker(choice[Envelope(prf(prf(prf(prf(key0,PROTOCOL),MAC),kem_pub(trusted_kem_sk(responder1))),
// // InitHello(secure_sidi, *epki2, *sctr2, *pidiC2, *auth2)
// // ), InitHello(secure_sidi, *epki2, *sctr2, *pidiC2, *auth2))
// // Envelope(prf(prf(prf(prf(key0,PROTOCOL),MAC),kem_pub(trusted_kem_sk(responder2))),
// // InitHello(secure_sidi, *epki, *sctr, *pidiC, *auth)),
// // InitHello(secure_sidi, *epki, *sctr, *pidiC, *auth))
// // ]) / 9999[hypothesis, conclusion].
// nounif k:key, b1:bits, b2:bits;
// attacker(xaead_enc( *k, *b1, *b2)) / 9999[hypothesis,conclusion].
// nounif pk:kem_pk, k:key;
// attacker(kem_enc( *pk , *k )) / 9999[hypothesis,conclusion].
// nounif sid:SessionId, biscuit_no:Atom, Ssskm:kem_sk_tmpl, Spsk:key_tmpl, Sspkt:kem_sk_tmpl, Septi:seed_tmpl, Sspti:seed_tmpl, ih:InitHello_t;
// attacker(Cinit_hello( *sid, *biscuit_no, *Ssskm, *Spsk, *Sspkt, *Septi, *Sspti, *ih ))/9999[hypothesis, conclusion].
// nounif Ssskm:kem_sk_tmpl, Spsk:key_tmpl, Sspkt:kem_sk_tmpl, ic:InitConf_t;
// attacker(Cinit_conf( *Ssskm, *Spsk, *Sspkt, *ic ))/9999[hypothesis, conclusion].
// nounif sid:SessionId, Ssskm:kem_sk_tmpl, Spsk:key_tmpl, Sspkt:kem_sk_tmpl, Seski:seed_tmpl, Ssptr:seed_tmpl;
// attacker(Cinitiator( *sid, *Ssskm, *Spsk, *Sspkt, *Seski, *Ssptr )) /9999 [hypothesis, conclusion].
// nounif sid:SessionId, biscuit_no:Atom, Ssskm:kem_sk_tmpl, Spsk:key_tmpl, Sspkt:kem_sk_tmpl, Septi:seed_tmpl, Sspti:seed_tmpl, ih:InitHello_t;
// mess(C, Cinit_hello( *sid, *biscuit_no, *Ssskm, *Spsk, *Sspkt, *Septi, *Sspti, *ih ))/9999[hypothesis, conclusion].
// nounif Ssskm:kem_sk_tmpl, Spsk:key_tmpl, Sspkt:kem_sk_tmpl, ic:InitConf_t;
// mess(C, Cinit_conf( *Ssskm, *Spsk, *Sspkt, *ic ))/9999[hypothesis, conclusion].
// nounif sid:SessionId, Ssskm:kem_sk_tmpl, Spsk:key_tmpl, Sspkt:kem_sk_tmpl, Seski:seed_tmpl, Ssptr:seed_tmpl;
// mess(C, Cinitiator( *sid, *Ssskm, *Spsk, *Sspkt, *Seski, *Ssptr )) /9999 [hypothesis, conclusion].
// nounif rh:RespHello_t;
// attacker(Cresp_hello( *rh ))[conclusion].
// nounif v:seed_prec; attacker(prepare_seed(trusted_seed( v )))/6217[hypothesis].
// nounif v:seed; attacker(prepare_seed( v ))/6216[hypothesis].
// nounif v:seed; attacker(rng_kem_sk( v ))/6215[hypothesis].
// nounif v:seed; attacker(rng_key( v ))/6214[hypothesis].
// nounif v:key_prec; attacker(prepare_key(trusted_key( v )))/6213[hypothesis].
// nounif v:kem_sk_prec; attacker(prepare_kem_sk(trusted_kem_sk( v )))/6212[hypothesis].
// nounif v:key; attacker(prepare_key( v ))/6211[hypothesis].
// nounif v:kem_sk; attacker(prepare_kem_sk( v ))/6210[hypothesis].

View File

@@ -0,0 +1,29 @@
#define INITIATOR_TEST 1
#define CUSTOM_MAIN 1
#include "rosenpass/03_identity_hiding.mpv"
let Oinitiator_bad_actor_inner(sk_tmp:kem_sk_prec) =
in(C, Cinitiator(sidi, Ssskm, Spsk, Sspkt, Seski, Ssptr));
#if RANDOMIZED_CALL_IDS
new call:Atom;
#else
call <- Cinitiator(sidi, Ssskm, Spsk, Sspkt, Seski, Ssptr);
#endif
in(C, last_cookie:key);
tmpl <- make_trusted_kem_sk(sk_tmp);
out(C, setup_kem_sk(tmpl));
Oinitiator_inner(sidi, Ssskm, Spsk, tmpl, Seski, Ssptr, last_cookie, C, call).
let Oinitiator_bad_actor() =
Oinitiator_bad_actor_inner(responder1) | Oinitiator_bad_actor_inner(responder2) | Oinitiator_bad_actor_inner(initiator1) | Oinitiator_bad_actor_inner(initiator2).
let identity_hiding_main2() =
0 | Oinitiator_bad_actor() | rosenpass_main2() | participants_communication() | phase 1; secretCommunication().
let main = identity_hiding_main2.

View File

@@ -0,0 +1,136 @@
#define CHAINING_KEY_EVENTS 1
#define MESSAGE_TRANSMISSION_EVENTS 0
#define SESSION_START_EVENTS 0
#define RANDOMIZED_CALL_IDS 0
#define COOKIE_EVENTS 1
#define KEM_EVENTS 1
#include "config.mpv"
#include "prelude/basic.mpv"
#include "crypto/key.mpv"
#include "crypto/kem.mpv"
#include "rosenpass/handshake_state.mpv"
/* The cookie data structure is implemented based on the WireGuard protocol.
* The ip and port is based purely on the public key and the implementation of the private cookie key is intended to mirror the biscuit key.
* The code tests the response to a possible DOS attack by setting up alternative branches for the protocol
* processes: Oinit_conf, Oinit_hello and resp_hello to simulate what happens when the responder or initiator is overloaded.
* When under heavy load a valid cookie is required. When such a cookie is not present a cookie message is sent as a response.
* Queries then test to make sure that expensive KEM operations are only conducted after a cookie has been successfully validated.
*/
type CookieMsg_t.
fun CookieMsg(
SessionId, // sender
bits, // nonce
bits // cookie
) : CookieMsg_t [data].
#define COOKIE_EVENTS(eventLbl) \
COOKIE_EV(event MCAT(eventLbl, _UnderLoadEV) (SessionId, SessionId, Atom).) \
COOKIE_EV(event MCAT(eventLbl, _CookieValidated) (SessionId, SessionId, Atom).) \
COOKIE_EV(event MCAT(eventLbl, _CookieSent) (SessionId, SessionId, Atom, CookieMsg_t).)
fun cookie_key(kem_sk) : key [private].
fun ip_and_port(kem_pk):bits.
letfun create_mac2_key(sskm:kem_sk, spkt:kem_pk) = prf(cookie_key(sskm), ip_and_port(spkt)).
letfun create_cookie(sskm:kem_sk, spkm:kem_pk, spkt:kem_pk, nonce:bits, msg:bits) = xaead_enc(lprf2(COOKIE, kem_pk2b(spkm), nonce),
k2b(create_mac2_key(sskm, spkm)), msg).
#define COOKIE_PROCESS(eventLbl, innerFunc) \
new nonce:bits; \
in(C, Ccookie(mac1, mac2)); \
COOKIE_EV(event MCAT(eventLbl, _UnderLoadEV) (sidi, sidr, call);) \
msgB <- Envelope(mac1, msg); \
mac2_key <- create_mac2_key(sskm, spkt); \
if k2b(create_mac2(mac2_key, msgB)) = mac2 then \
COOKIE_EV(event MCAT(eventLbl, _CookieValidated) (sidi, sidr, call);) \
innerFunc \
else \
cookie <- create_cookie(sskm, spkm, spkt, nonce, msg); \
cookie_msg <- CookieMsg(sidi, nonce, cookie); \
COOKIE_EV(event MCAT(eventLbl, _CookieSent) (sidi, sidr, call, cookie_msg);) \
out(C, cookie_msg). \
#include "rosenpass/oracles.mpv"
#include "rosenpass/responder.macro"
COOKIE_EVENTS(Oinit_conf)
let Oinit_conf_underLoad() =
in(C, Cinit_conf(Ssskm, Spsk, Sspkt, ic));
in(C, last_cookie:bits);
msg <- IC2b(ic);
let InitConf(sidi, sidr, biscuit, auth) = ic in
new call:Atom;
SETUP_HANDSHAKE_STATE()
COOKIE_PROCESS(Oinit_conf, Oinit_conf_inner(Ssskm, Spsk, Sspkt, ic, call))
#include "rosenpass/responder.macro"
COOKIE_EVENTS(Oinit_hello)
let Oinit_hello_underLoad() =
in(C, Cinit_hello(sidr, biscuit_no, Ssskm, Spsk, Sspkt, Septi, Sspti, ih));
in(C, Oinit_hello_last_cookie:key);
new call:Atom;
msg <- IH2b(ih);
let InitHello(sidi, epki, sctr, pidic, auth) = ih in
SETUP_HANDSHAKE_STATE()
COOKIE_PROCESS(Oinit_hello, Oinit_hello_inner(sidr, biscuit_no, Ssskm, Spsk, Sspkt, Septi, Sspti, ih, Oinit_hello_last_cookie, C, call))
let rosenpass_dos_main() = 0
| !Oreveal_kem_pk
| REP(INITIATOR_BOUND, Oinitiator)
| REP(RESPONDER_BOUND, Oinit_hello)
| REP(RESPONDER_BOUND, Oinit_conf)
| REP(RESPONDER_BOUND, Oinit_hello_underLoad)
| REP(RESPONDER_BOUND, Oinit_conf_underLoad).
let main = rosenpass_dos_main.
select cookie:CookieMsg_t; attacker(cookie)/6220[hypothesis].
nounif v:key; attacker(prepare_key( v ))/6217[hypothesis].
nounif v:seed; attacker(prepare_seed( v ))/6216[hypothesis].
nounif v:seed; attacker(prepare_seed( v ))/6216[hypothesis].
nounif v:seed; attacker(rng_kem_sk( v ))/6215[hypothesis].
nounif v:seed; attacker(rng_key( v ))/6214[hypothesis].
nounif v:kem_sk; attacker(prepare_kem_sk( v ))/6210[hypothesis].
// nounif Spk:kem_sk_tmpl;
// attacker(Creveal_kem_pk(Spk))/6110[conclusion].
// nounif sid:SessionId, Ssskm:kem_sk_tmpl, Spsk:key_tmpl, Sspkt:kem_sk_tmpl, Seski:seed_tmpl, Ssptr:seed_tmpl;
// attacker(Cinitiator( *sid, *Ssskm, *Spsk, *Sspkt, *Seski, *Ssptr ))/6109[conclusion].
// nounif sid:SessionId, biscuit_no:Atom, Ssskm:kem_sk_tmpl, Spsk:key_tmpl, Sspkt:kem_sk_tmpl, Septi:seed_tmpl, Sspti:seed_tmpl, ih:InitHello_t;
// attacker(Cinit_hello( *sid, *biscuit_no, *Ssskm, *Spsk, *Sspkt, *Septi, *Sspti, *ih ))/6108[conclusion].
nounif rh:RespHello_t;
attacker(Cresp_hello( *rh ))/6107[conclusion].
nounif Ssskm:kem_sk_tmpl, Spsk:key_tmpl, Sspkt:kem_sk_tmpl, ic:InitConf_t;
attacker(Cinit_conf( *Ssskm, *Spsk, *Sspkt, *ic ))/6106[conclusion].
@reachable "DOS protection: cookie sent"
query sidi:SessionId, sidr:SessionId, call:Atom, cookieMsg:CookieMsg_t;
event (Oinit_hello_CookieSent(sidi, sidr, call, cookieMsg)).
@lemma "DOS protection: Oinit_hello kem use when under load implies validated cookie"
lemma sidi:SessionId, sidr:SessionId, call:Atom;
event(Oinit_hello_UnderLoadEV(sidi, sidr, call))
&& event(Oinit_hello_KemUse(sidi, sidr, call))
==> event(Oinit_hello_CookieValidated(sidi, sidr, call)).
@lemma "DOS protection: Oinit_conf kem use when under load implies validated cookie"
lemma sidi:SessionId, sidr:SessionId, call:Atom;
event(Oinit_conf_UnderLoadEV(sidi, sidr, call))
&& event(Oinit_conf_KemUse(sidi, sidr, call))
==> event(Oinit_conf_CookieValidated(sidi, sidr, call)).
@lemma "DOS protection: Oresp_hello kem use when under load implies validated cookie"
lemma sidi:SessionId, sidr:SessionId, call:Atom;
event(Oresp_hello_UnderLoadEV(sidi, sidr, call))
&& event(Oresp_hello_KemUse(sidi, sidr, call))
==> event(Oresp_hello_CookieValidated(sidi, sidr, call)).

View File

@@ -0,0 +1,155 @@
/*
This identity hiding process tests whether the rosenpass protocol is able to protect the identity of an initiator or responder.
The participants in the test are trusted initiators, trusted responders and compromised initiators and responders.
The test consists of two phases. In the first phase all of the participants can communicate with each other using the rosenpass protocol.
An attacker observes the first phase and is able to intercept and modify messages and choose participants to communicate with each other
In the second phase if the anonymity of an initiator is being tested then one of two trusted initiators is chosen.
The chosen initiator communicates directly with a trusted responder.
If an attacker can determine which initiator was chosen then the anonymity of the initiator has been compromised.
Otherwise the protocol has successfully protected the initiators identity.
If the anonymity of a responder is being tested then one of two trusted responders is chosen instead.
Then an initiator communicates directly with the chosen responder.
If an attacker can determine which responder was chosen then the anonymity of the responder is compromised.
Otherwise the protocol successfully protects the identity of a responder.
The Proverif code treats the public key as synonymous with identity.
In the above test when a responder or initiator is chosen what is actually chosen is the public/private key pair to use for communication.
Traditionally when a responder or initiator is chosen they would be chosen randomly.
The way Proverif makes a "choice" is by simulating multiple processes, one process per choice
Then the processes are compared and if an association between a public key and a process can be made the test fails.
As the choice is at least as bad as choosing the worst possible option the credibility of the test is maintained.
The drawback is that Proverif is only able to tell if the identity can be brute forced but misses any probabilistic associations.
As usual Proverif also assumes perfect encryption and in particular assumes encryption cannot be linked to identity.
One of the tradeoffs made here is that the choice function in Proverif is slow but this is in favour of being able to write more precise tests.
Another issue is the choice function does not work with queries so a test needs to be run for each set of assumptions.
In this case the test uses secure rng and a fresh secure biscuit key.
*/
#include "config.mpv"
#define CHAINING_KEY_EVENTS 1
#define MESSAGE_TRANSMISSION_EVENTS 1
#define SESSION_START_EVENTS 0
#define RANDOMIZED_CALL_IDS 0
#undef FULL_MODEL
#undef SIMPLE_MODEL
#define SIMPLE_MODEL 1
#include "prelude/basic.mpv"
#include "crypto/key.mpv"
#include "rosenpass/oracles.mpv"
#include "crypto/kem.mpv"
#define NEW_TRUSTED_SEED(name) \
new MCAT(name, _secret_seed):seed_prec; \
name <- make_trusted_seed(MCAT(name, _secret_seed)); \
free D:channel [private].
free secure_biscuit_no:Atom [private].
free secure_sidi,secure_sidr:SessionId [private].
free secure_psk:key [private].
free initiator1, initiator2:kem_sk_prec.
free responder1, responder2:kem_sk_prec.
let secure_init_hello(initiator: kem_sk_tmpl, sidi : SessionId, psk: key_tmpl, responder: kem_sk_tmpl) =
new epkit:kem_pk; // epki
new sctrt:bits; // sctr
new pidiCt:bits; // pidiC
new autht:bits; // auth
NEW_TRUSTED_SEED(seski_trusted_seed)
NEW_TRUSTED_SEED(ssptr_trusted_seed)
new last_cookie:key;
new call:Atom;
Oinitiator_inner(sidi, initiator, psk, responder, seski_trusted_seed, ssptr_trusted_seed, last_cookie, D, call).
let secure_resp_hello(initiator: kem_sk_tmpl, responder: kem_sk_tmpl, sidi:SessionId, sidr:SessionId, biscuit_no:Atom, psk:key_tmpl) =
in(D, InitHello(=secure_sidi, epki, sctr, pidiC, auth));
ih <- InitHello(sidi, epki, sctr, pidiC, auth);
NEW_TRUSTED_SEED(septi_trusted_seed)
NEW_TRUSTED_SEED(sspti_trusted_seed)
new last_cookie:key;
new call:Atom;
Oinit_hello_inner(sidr, biscuit_no, responder, psk, initiator, septi_trusted_seed, sspti_trusted_seed, ih, last_cookie, D, call).
let secure_init_conf(initiator: kem_sk_tmpl, responder: kem_sk_tmpl, psk:key_tmpl, sidi:SessionId, sidr:SessionId) =
in(D, InitConf(=sidi, =sidr, biscuit, auth3));
ic <- InitConf(sidi,sidr,biscuit, auth3);
NEW_TRUSTED_SEED(seski_trusted_seed)
NEW_TRUSTED_SEED(ssptr_trusted_seed)
new last_cookie:key;
call <- Cinit_conf(initiator, psk, responder, ic);
Oinit_conf_inner(initiator, psk, responder, ic, call).
let secure_communication(initiator: kem_sk_tmpl, responder:kem_sk_tmpl, key:key) =
key_tmpl <- prepare_key(key);
(!secure_init_hello(initiator, secure_sidi, key_tmpl, responder))
| !secure_resp_hello(initiator, responder, secure_sidi, secure_sidr, secure_biscuit_no, key_tmpl)
| !(secure_init_conf(initiator, responder, key_tmpl, secure_sidi, secure_sidr)).
let participant_communication_initiator(participant:kem_sk_tmpl) =
in(C, responder:kem_sk_tmpl);
in(C, k:key);
secure_communication(participant, responder, k).
let participant_communication_responder(participant:kem_sk_tmpl) =
in(C, initiator:kem_sk_tmpl);
in(C, k:key);
secure_communication(initiator, participant, k).
let participants_communication() =
initiator1_tmpl <- make_trusted_kem_sk(initiator1);
initiator2_tmpl <- make_trusted_kem_sk(initiator2);
responder1_tmpl <- make_trusted_kem_sk(responder1);
responder2_tmpl <- make_trusted_kem_sk(responder2);
!participant_communication_initiator(initiator1_tmpl) | !participant_communication_responder(initiator1_tmpl)
| !participant_communication_initiator(initiator2_tmpl) | !participant_communication_responder(initiator2_tmpl)
| !participant_communication_initiator(responder1_tmpl) | !participant_communication_responder(responder1_tmpl)
| !participant_communication_initiator(responder2_tmpl) | !participant_communication_responder(responder2_tmpl).
let pipeChannel(D:channel, C:channel) =
in(D, b:bits);
out(C, b).
let secretCommunication() =
#ifdef INITIATOR_TEST
initiator_seed <- choice[make_trusted_kem_sk(initiator1), make_trusted_kem_sk(initiator2)];
#else
initiator_seed <- make_trusted_kem_sk(initiator1);
#endif
#ifdef RESPONDER_TEST
responder_seed <- choice[make_trusted_kem_sk(responder1), make_trusted_kem_sk(responder2)];
#else
responder_seed <- make_trusted_kem_sk(responder1);
#endif
secure_communication(initiator_seed, responder_seed, secure_psk) | !pipeChannel(D, C).
let reveal_pks() =
out(C, setup_kem_pk(make_trusted_kem_sk(responder1)));
out(C, setup_kem_pk(make_trusted_kem_sk(responder2)));
out(C, setup_kem_pk(make_trusted_kem_sk(initiator1)));
out(C, setup_kem_pk(make_trusted_kem_sk(initiator2))).
let rosenpass_main2() =
REP(INITIATOR_BOUND, Oinitiator)
| REP(RESPONDER_BOUND, Oinit_hello)
| REP(RESPONDER_BOUND, Oinit_conf).
let identity_hiding_main() =
0 | reveal_pks() | rosenpass_main2() | participants_communication() | phase 1; secretCommunication().
#ifndef CUSTOM_MAIN
let main = identity_hiding_main.
#endif

View File

@@ -0,0 +1,36 @@
fun cookie_key(kem_sk) : key [private].
fun ip_and_port(kem_pk):bits.
letfun create_mac2_key(sskm:kem_sk, spkt:kem_pk) = prf(cookie_key(sskm), ip_and_port(spkt)).
letfun create_cookie(sskm:kem_sk, spkm:kem_pk, spkt:kem_pk, nonce:bits, msg:bits) = xaead_enc(lprf2(COOKIE, kem_pk2b(spkm), nonce),
k2b(create_mac2_key(sskm, spkm)), msg).
type CookieMsg_t.
fun CookieMsg(
SessionId, // sender
bits, // nonce
bits // cookie
) : CookieMsg_t [data].
#define COOKIE_PROCESS(eventLbl, innerFunc) \
in(C, Ccookie(mac1, mac2)); \
COOKIE_EV(event MCAT(eventLbl, _UnderLoadEV) (spkm, spkt, last_cookie);) \
msgB <- Envelope(mac1, RH2b(rh)); \
mac2_key <- create_mac2_key(sskm, spkt) \
let RespHello(sidi, sidr, ecti, scti, biscuit, auth) = rh in \
if Envelope(mac2_key, msgB) = mac2 then \
COOKIE_EV(event MCAT(eventLbl, _CookieValidated) (spkm, last_cookie);) \
innerFunc \
else \
new nonce:bits; \
cookie <- create_cookie(sskm, spkm, spkt, nonce, msg) \
cookie_msg <- CookieMsg(sidi, nonce, cookie); \
COOKIE_EV(event MCAT(eventLbl, _CookieSent) (spkm, cookie, cookie_k, cookie_msg);) \
out(C, cookie_msg).
#define COOKIE_EVENTS(eventLbl) \
COOKIE_EV(event MCAT(eventLbl, _UnderLoadEV) (kem_pk, kem_pk, bits).) \
COOKIE_EV(event MCAT(eventLbl, _CookieValidated) (kem_pk, bits, key, CookieMsg_t).) \
COOKIE_EV(event MCAT(eventLbl, _CookieSent) (kem_pk, bits).)

12
cipher-traits/Cargo.toml Normal file
View File

@@ -0,0 +1,12 @@
[package]
name = "rosenpass-cipher-traits"
authors = ["Karolin Varner <karo@cupdev.net>", "wucke13 <wucke13@gmail.com>"]
version = "0.1.0"
edition = "2021"
license = "MIT OR Apache-2.0"
description = "Rosenpass internal traits for cryptographic primitives"
homepage = "https://rosenpass.eu/"
repository = "https://github.com/rosenpass/rosenpass"
readme = "readme.md"
[dependencies]

5
cipher-traits/readme.md Normal file
View File

@@ -0,0 +1,5 @@
# Rosenpass internal cryptographic traits
Rosenpass internal library providing traits for cryptographic primitives.
This is an internal library; not guarantee is made about its API at this point in time.

45
cipher-traits/src/kem.rs Normal file
View File

@@ -0,0 +1,45 @@
//! Traits and implementations for Key Encapsulation Mechanisms (KEMs)
//!
//! KEMs are the interface provided by almost all post-quantum
//! secure key exchange mechanisms.
//!
//! Conceptually KEMs are akin to public-key encryption, but instead of encrypting
//! arbitrary data, KEMs are limited to the transmission of keys, randomly chosen during
//!
//! encapsulation.
//! The [KEM] Trait describes the basic API offered by a Key Encapsulation
//! Mechanism. Two implementations for it are provided, [StaticKEM] and [EphemeralKEM].
/// Key Encapsulation Mechanism
///
/// The KEM interface defines three operations: Key generation, key encapsulation and key
/// decapsulation.
pub trait Kem {
type Error;
/// Secrete Key length
const SK_LEN: usize;
/// Public Key length
const PK_LEN: usize;
/// Ciphertext length
const CT_LEN: usize;
/// Shared Secret length
const SHK_LEN: usize;
/// Generate a keypair consisting of secret key (`sk`) and public key (`pk`)
///
/// `keygen() -> sk, pk`
fn keygen(sk: &mut [u8], pk: &mut [u8]) -> Result<(), Self::Error>;
/// From a public key (`pk`), generate a shared key (`shk`, for local use)
/// and a cipher text (`ct`, to be sent to the owner of the `pk`).
///
/// `encaps(pk) -> shk, ct`
fn encaps(shk: &mut [u8], ct: &mut [u8], pk: &[u8]) -> Result<(), Self::Error>;
/// From a secret key (`sk`) and a cipher text (`ct`) derive a shared key
/// (`shk`)
///
/// `decaps(sk, ct) -> shk`
fn decaps(shk: &mut [u8], sk: &[u8], ct: &[u8]) -> Result<(), Self::Error>;
}

2
cipher-traits/src/lib.rs Normal file
View File

@@ -0,0 +1,2 @@
mod kem;
pub use kem::Kem;

26
ciphers/Cargo.toml Normal file
View File

@@ -0,0 +1,26 @@
[package]
name = "rosenpass-ciphers"
authors = ["Karolin Varner <karo@cupdev.net>", "wucke13 <wucke13@gmail.com>"]
version = "0.1.0"
edition = "2021"
license = "MIT OR Apache-2.0"
description = "Rosenpass internal ciphers and other cryptographic primitives used by rosenpass."
homepage = "https://rosenpass.eu/"
repository = "https://github.com/rosenpass/rosenpass"
readme = "readme.md"
[features]
experiment_libcrux = ["dep:libcrux"]
[dependencies]
anyhow = { workspace = true }
rosenpass-to = { workspace = true }
rosenpass-constant-time = { workspace = true }
rosenpass-secret-memory = { workspace = true }
rosenpass-oqs = { workspace = true }
rosenpass-util = { workspace = true }
static_assertions = { workspace = true }
zeroize = { workspace = true }
chacha20poly1305 = { workspace = true }
blake2 = { workspace = true }
libcrux = { workspace = true, optional = true }

5
ciphers/readme.md Normal file
View File

@@ -0,0 +1,5 @@
# Rosenpass internal cryptographic primitives
Ciphers and other cryptographic primitives used by rosenpass.
This is an internal library; not guarantee is made about its API at this point in time.

109
ciphers/src/hash_domain.rs Normal file
View File

@@ -0,0 +1,109 @@
use anyhow::Result;
use rosenpass_secret_memory::Secret;
use rosenpass_to::To;
use crate::subtle::incorrect_hmac_blake2b as hash;
pub use hash::KEY_LEN;
// TODO Use a proper Dec interface
#[derive(Clone, Debug)]
pub struct HashDomain([u8; KEY_LEN]);
#[derive(Clone, Debug)]
pub struct HashDomainNamespace([u8; KEY_LEN]);
#[derive(Clone, Debug)]
pub struct SecretHashDomain(Secret<KEY_LEN>);
#[derive(Clone, Debug)]
pub struct SecretHashDomainNamespace(Secret<KEY_LEN>);
impl HashDomain {
pub fn zero() -> Self {
Self([0u8; KEY_LEN])
}
pub fn dup(self) -> HashDomainNamespace {
HashDomainNamespace(self.0)
}
pub fn turn_secret(self) -> SecretHashDomain {
SecretHashDomain(Secret::from_slice(&self.0))
}
// TODO: Protocol! Use domain separation to ensure that
pub fn mix(self, v: &[u8]) -> Result<Self> {
Ok(Self(hash::hash(&self.0, v).collect::<[u8; KEY_LEN]>()?))
}
pub fn mix_secret<const N: usize>(self, v: Secret<N>) -> Result<SecretHashDomain> {
SecretHashDomain::invoke_primitive(&self.0, v.secret())
}
pub fn into_value(self) -> [u8; KEY_LEN] {
self.0
}
}
impl HashDomainNamespace {
pub fn mix(&self, v: &[u8]) -> Result<HashDomain> {
Ok(HashDomain(
hash::hash(&self.0, v).collect::<[u8; KEY_LEN]>()?,
))
}
pub fn mix_secret<const N: usize>(&self, v: Secret<N>) -> Result<SecretHashDomain> {
SecretHashDomain::invoke_primitive(&self.0, v.secret())
}
}
impl SecretHashDomain {
pub fn invoke_primitive(k: &[u8], d: &[u8]) -> Result<SecretHashDomain> {
let mut r = SecretHashDomain(Secret::zero());
hash::hash(k, d).to(r.0.secret_mut())?;
Ok(r)
}
pub fn zero() -> Self {
Self(Secret::zero())
}
pub fn dup(self) -> SecretHashDomainNamespace {
SecretHashDomainNamespace(self.0)
}
pub fn danger_from_secret(k: Secret<KEY_LEN>) -> Self {
Self(k)
}
pub fn mix(self, v: &[u8]) -> Result<SecretHashDomain> {
Self::invoke_primitive(self.0.secret(), v)
}
pub fn mix_secret<const N: usize>(self, v: Secret<N>) -> Result<SecretHashDomain> {
Self::invoke_primitive(self.0.secret(), v.secret())
}
pub fn into_secret(self) -> Secret<KEY_LEN> {
self.0
}
pub fn into_secret_slice(mut self, v: &[u8], dst: &[u8]) -> Result<()> {
hash::hash(v, dst).to(self.0.secret_mut())
}
}
impl SecretHashDomainNamespace {
pub fn mix(&self, v: &[u8]) -> Result<SecretHashDomain> {
SecretHashDomain::invoke_primitive(self.0.secret(), v)
}
pub fn mix_secret<const N: usize>(&self, v: Secret<N>) -> Result<SecretHashDomain> {
SecretHashDomain::invoke_primitive(self.0.secret(), v.secret())
}
// TODO: This entire API is not very nice; we need this for biscuits, but
// it might be better to extract a special "biscuit"
// labeled subkey and reinitialize the chain with this
pub fn danger_into_secret(self) -> Secret<KEY_LEN> {
self.0
}
}

32
ciphers/src/lib.rs Normal file
View File

@@ -0,0 +1,32 @@
use static_assertions::const_assert;
pub mod subtle;
pub const KEY_LEN: usize = 32;
const_assert!(KEY_LEN == aead::KEY_LEN);
const_assert!(KEY_LEN == xaead::KEY_LEN);
const_assert!(KEY_LEN == hash_domain::KEY_LEN);
/// Authenticated encryption with associated data
pub mod aead {
#[cfg(not(feature = "experiment_libcrux"))]
pub use crate::subtle::chacha20poly1305_ietf::{decrypt, encrypt, KEY_LEN, NONCE_LEN, TAG_LEN};
#[cfg(feature = "experiment_libcrux")]
pub use crate::subtle::chacha20poly1305_ietf_libcrux::{
decrypt, encrypt, KEY_LEN, NONCE_LEN, TAG_LEN,
};
}
/// Authenticated encryption with associated data with a constant nonce
pub mod xaead {
pub use crate::subtle::xchacha20poly1305_ietf::{
decrypt, encrypt, KEY_LEN, NONCE_LEN, TAG_LEN,
};
}
pub mod hash_domain;
pub mod kem {
pub use rosenpass_oqs::ClassicMceliece460896 as StaticKem;
pub use rosenpass_oqs::Kyber512 as EphemeralKem;
}

View File

@@ -0,0 +1,42 @@
use zeroize::Zeroizing;
use blake2::digest::crypto_common::generic_array::GenericArray;
use blake2::digest::crypto_common::typenum::U32;
use blake2::digest::crypto_common::KeySizeUser;
use blake2::digest::{FixedOutput, Mac, OutputSizeUser};
use blake2::Blake2bMac;
use rosenpass_to::{ops::copy_slice, with_destination, To};
use rosenpass_util::typenum2const;
type Impl = Blake2bMac<U32>;
type KeyLen = <Impl as KeySizeUser>::KeySize;
type OutLen = <Impl as OutputSizeUser>::OutputSize;
const KEY_LEN: usize = typenum2const! { KeyLen };
const OUT_LEN: usize = typenum2const! { OutLen };
pub const KEY_MIN: usize = KEY_LEN;
pub const KEY_MAX: usize = KEY_LEN;
pub const OUT_MIN: usize = OUT_LEN;
pub const OUT_MAX: usize = OUT_LEN;
#[inline]
pub fn hash<'a>(key: &'a [u8], data: &'a [u8]) -> impl To<[u8], anyhow::Result<()>> + 'a {
with_destination(|out: &mut [u8]| {
let mut h = Impl::new_from_slice(key)?;
h.update(data);
// Jesus christ, blake2 crate, your usage of GenericArray might be nice and fancy
// but it introduces a ton of complexity. This cost me half an hour just to figure
// out the right way to use the imports while allowing for zeroization.
// An API based on slices might actually be simpler.
let mut tmp = Zeroizing::new([0u8; OUT_LEN]);
let tmp = GenericArray::from_mut_slice(tmp.as_mut());
h.finalize_into(tmp);
copy_slice(tmp.as_ref()).to(out);
Ok(())
})
}

View File

@@ -0,0 +1,43 @@
use rosenpass_to::ops::copy_slice;
use rosenpass_to::To;
use rosenpass_util::typenum2const;
use chacha20poly1305::aead::generic_array::GenericArray;
use chacha20poly1305::ChaCha20Poly1305 as AeadImpl;
use chacha20poly1305::{AeadCore, AeadInPlace, KeyInit, KeySizeUser};
pub const KEY_LEN: usize = typenum2const! { <AeadImpl as KeySizeUser>::KeySize };
pub const TAG_LEN: usize = typenum2const! { <AeadImpl as AeadCore>::TagSize };
pub const NONCE_LEN: usize = typenum2const! { <AeadImpl as AeadCore>::NonceSize };
#[inline]
pub fn encrypt(
ciphertext: &mut [u8],
key: &[u8],
nonce: &[u8],
ad: &[u8],
plaintext: &[u8],
) -> anyhow::Result<()> {
let nonce = GenericArray::from_slice(nonce);
let (ct, mac) = ciphertext.split_at_mut(ciphertext.len() - TAG_LEN);
copy_slice(plaintext).to(ct);
let mac_value = AeadImpl::new_from_slice(key)?.encrypt_in_place_detached(nonce, ad, ct)?;
copy_slice(&mac_value[..]).to(mac);
Ok(())
}
#[inline]
pub fn decrypt(
plaintext: &mut [u8],
key: &[u8],
nonce: &[u8],
ad: &[u8],
ciphertext: &[u8],
) -> anyhow::Result<()> {
let nonce = GenericArray::from_slice(nonce);
let (ct, mac) = ciphertext.split_at(ciphertext.len() - TAG_LEN);
let tag = GenericArray::from_slice(mac);
copy_slice(ct).to(plaintext);
AeadImpl::new_from_slice(key)?.decrypt_in_place_detached(nonce, ad, plaintext, tag)?;
Ok(())
}

View File

@@ -0,0 +1,60 @@
use rosenpass_to::ops::copy_slice;
use rosenpass_to::To;
use zeroize::Zeroize;
pub const KEY_LEN: usize = 32; // Grrrr! Libcrux, please provide me these constants.
pub const TAG_LEN: usize = 16;
pub const NONCE_LEN: usize = 12;
#[inline]
pub fn encrypt(
ciphertext: &mut [u8],
key: &[u8],
nonce: &[u8],
ad: &[u8],
plaintext: &[u8],
) -> anyhow::Result<()> {
let (ciphertext, mac) = ciphertext.split_at_mut(ciphertext.len() - TAG_LEN);
use libcrux::aead as C;
let crux_key = C::Key::Chacha20Poly1305(C::Chacha20Key(key.try_into().unwrap()));
let crux_iv = C::Iv(nonce.try_into().unwrap());
copy_slice(plaintext).to(ciphertext);
let crux_tag = libcrux::aead::encrypt(&crux_key, ciphertext, crux_iv, ad).unwrap();
copy_slice(crux_tag.as_ref()).to(mac);
match crux_key {
C::Key::Chacha20Poly1305(mut k) => k.0.zeroize(),
_ => panic!(),
}
Ok(())
}
#[inline]
pub fn decrypt(
plaintext: &mut [u8],
key: &[u8],
nonce: &[u8],
ad: &[u8],
ciphertext: &[u8],
) -> anyhow::Result<()> {
let (ciphertext, mac) = ciphertext.split_at(ciphertext.len() - TAG_LEN);
use libcrux::aead as C;
let crux_key = C::Key::Chacha20Poly1305(C::Chacha20Key(key.try_into().unwrap()));
let crux_iv = C::Iv(nonce.try_into().unwrap());
let crux_tag = C::Tag::from_slice(mac).unwrap();
copy_slice(ciphertext).to(plaintext);
libcrux::aead::decrypt(&crux_key, plaintext, crux_iv, ad, &crux_tag).unwrap();
match crux_key {
C::Key::Chacha20Poly1305(mut k) => k.0.zeroize(),
_ => panic!(),
}
Ok(())
}

View File

@@ -0,0 +1,46 @@
use anyhow::ensure;
use zeroize::Zeroizing;
use rosenpass_constant_time::xor;
use rosenpass_to::{ops::copy_slice, with_destination, To};
use crate::subtle::blake2b;
pub const KEY_LEN: usize = 32;
pub const KEY_MIN: usize = KEY_LEN;
pub const KEY_MAX: usize = KEY_LEN;
pub const OUT_MIN: usize = blake2b::OUT_MIN;
pub const OUT_MAX: usize = blake2b::OUT_MAX;
/// This is a woefully incorrect implementation of hmac_blake2b.
/// See <https://github.com/rosenpass/rosenpass/issues/68#issuecomment-1563612222>
///
/// It accepts 32 byte keys, exclusively.
///
/// This will be replaced, likely by Kekkac at some point soon.
/// <https://github.com/rosenpass/rosenpass/pull/145>
#[inline]
pub fn hash<'a>(key: &'a [u8], data: &'a [u8]) -> impl To<[u8], anyhow::Result<()>> + 'a {
const IPAD: [u8; KEY_LEN] = [0x36u8; KEY_LEN];
const OPAD: [u8; KEY_LEN] = [0x5Cu8; KEY_LEN];
with_destination(|out: &mut [u8]| {
// Not bothering with padding; the implementation
// uses appropriately sized keys.
ensure!(key.len() == KEY_LEN);
type Key = Zeroizing<[u8; KEY_LEN]>;
let mut tmp_key = Key::default();
copy_slice(key).to(tmp_key.as_mut());
xor(&IPAD).to(tmp_key.as_mut());
let mut outer_data = Key::default();
blake2b::hash(tmp_key.as_ref(), data).to(outer_data.as_mut())?;
copy_slice(key).to(tmp_key.as_mut());
xor(&OPAD).to(tmp_key.as_mut());
blake2b::hash(tmp_key.as_ref(), outer_data.as_ref()).to(out)?;
Ok(())
})
}

View File

@@ -0,0 +1,7 @@
pub mod blake2b;
#[cfg(not(feature = "experiment_libcrux"))]
pub mod chacha20poly1305_ietf;
#[cfg(feature = "experiment_libcrux")]
pub mod chacha20poly1305_ietf_libcrux;
pub mod incorrect_hmac_blake2b;
pub mod xchacha20poly1305_ietf;

View File

@@ -0,0 +1,45 @@
use rosenpass_to::ops::copy_slice;
use rosenpass_to::To;
use rosenpass_util::typenum2const;
use chacha20poly1305::aead::generic_array::GenericArray;
use chacha20poly1305::XChaCha20Poly1305 as AeadImpl;
use chacha20poly1305::{AeadCore, AeadInPlace, KeyInit, KeySizeUser};
pub const KEY_LEN: usize = typenum2const! { <AeadImpl as KeySizeUser>::KeySize };
pub const TAG_LEN: usize = typenum2const! { <AeadImpl as AeadCore>::TagSize };
pub const NONCE_LEN: usize = typenum2const! { <AeadImpl as AeadCore>::NonceSize };
#[inline]
pub fn encrypt(
ciphertext: &mut [u8],
key: &[u8],
nonce: &[u8],
ad: &[u8],
plaintext: &[u8],
) -> anyhow::Result<()> {
let nonce = GenericArray::from_slice(nonce);
let (n, ct_mac) = ciphertext.split_at_mut(NONCE_LEN);
let (ct, mac) = ct_mac.split_at_mut(ct_mac.len() - TAG_LEN);
copy_slice(nonce).to(n);
copy_slice(plaintext).to(ct);
let mac_value = AeadImpl::new_from_slice(key)?.encrypt_in_place_detached(nonce, ad, ct)?;
copy_slice(&mac_value[..]).to(mac);
Ok(())
}
#[inline]
pub fn decrypt(
plaintext: &mut [u8],
key: &[u8],
ad: &[u8],
ciphertext: &[u8],
) -> anyhow::Result<()> {
let (n, ct_mac) = ciphertext.split_at(NONCE_LEN);
let (ct, mac) = ct_mac.split_at(ct_mac.len() - TAG_LEN);
let nonce = GenericArray::from_slice(n);
let tag = GenericArray::from_slice(mac);
copy_slice(ct).to(plaintext);
AeadImpl::new_from_slice(key)?.decrypt_in_place_detached(nonce, ad, plaintext, tag)?;
Ok(())
}

22
constant-time/Cargo.toml Normal file
View File

@@ -0,0 +1,22 @@
[package]
name = "rosenpass-constant-time"
version = "0.1.0"
authors = ["Karolin Varner <karo@cupdev.net>", "wucke13 <wucke13@gmail.com>"]
edition = "2021"
license = "MIT OR Apache-2.0"
description = "Rosenpass internal utilities for constant time crypto implementations"
homepage = "https://rosenpass.eu/"
repository = "https://github.com/rosenpass/rosenpass"
readme = "readme.md"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[features]
constant_time_tests = []
[dependencies]
rosenpass-to = { workspace = true }
memsec = { workspace = true }
[dev-dependencies]
rand = "0.8.5"

5
constant-time/readme.md Normal file
View File

@@ -0,0 +1,5 @@
# Rosenpass constant time library
Rosenpass internal library providing basic constant-time operations.
This is an internal library; not guarantee is made about its API at this point in time.

View File

@@ -0,0 +1,39 @@
use core::ptr;
/// Little endian memcmp version of quinier/memsec
/// https://github.com/quininer/memsec/blob/bbc647967ff6d20d6dccf1c85f5d9037fcadd3b0/src/lib.rs#L30
#[inline(never)]
pub unsafe fn memcmp_le(b1: *const u8, b2: *const u8, len: usize) -> i32 {
let mut res = 0;
for i in 0..len {
let diff =
i32::from(ptr::read_volatile(b1.add(i))) - i32::from(ptr::read_volatile(b2.add(i)));
res = (res & (((diff - 1) & !diff) >> 8)) | diff;
}
((res - 1) >> 8) + (res >> 8) + 1
}
/// compares two slices of memory content and returns an integer indicating the relationship between
/// the slices
///
/// ## Returns
/// - <0 if the first byte that does not match both slices has a lower value in `a` than in `b`
/// - 0 if the contents are equal
/// - >0 if the first byte that does not match both slices has a higher value in `a` than in `b`
///
/// ## Leaks
/// If the two slices have differents lengths, the function will return immediately. This
/// effectively leaks the information whether the slices have equal length or not. This is widely
/// considered safe.
///
/// The execution time of the function grows approx. linear with the length of the input. This is
/// considered safe.
///
/// ## Tests
/// For discussion on how to ensure the constant-time execution of this function, see
/// <https://github.com/rosenpass/rosenpass/issues/232>
#[inline]
pub fn compare(a: &[u8], b: &[u8]) -> i32 {
assert!(a.len() == b.len());
unsafe { memcmp_le(a.as_ptr(), b.as_ptr(), a.len()) }
}

View File

@@ -0,0 +1,48 @@
use core::hint::black_box;
/// Interpret the given slice as a little-endian unsigned integer
/// and increment that integer.
///
/// # Leaks
/// TODO: mention here if this function leaks any information, see
/// <https://github.com/rosenpass/rosenpass/issues/232>
///
/// ## Tests
/// For discussion on how to ensure the constant-time execution of this function, see
/// <https://github.com/rosenpass/rosenpass/issues/232>
///
/// # Examples
///
/// ```
/// use rosenpass_constant_time::increment as inc;
/// use rosenpass_to::To;
///
/// fn testcase(v: &[u8], correct: &[u8]) {
/// let mut v = v.to_owned();
/// inc(&mut v);
/// assert_eq!(&v, correct);
/// }
///
/// testcase(b"", b"");
/// testcase(b"\x00", b"\x01");
/// testcase(b"\x01", b"\x02");
/// testcase(b"\xfe", b"\xff");
/// testcase(b"\xff", b"\x00");
/// testcase(b"\x00\x00", b"\x01\x00");
/// testcase(b"\x01\x00", b"\x02\x00");
/// testcase(b"\xfe\x00", b"\xff\x00");
/// testcase(b"\xff\x00", b"\x00\x01");
/// testcase(b"\x00\x00\x00\x00\x00\x00", b"\x01\x00\x00\x00\x00\x00");
/// testcase(b"\x00\xa3\x00\x77\x00\x00", b"\x01\xa3\x00\x77\x00\x00");
/// testcase(b"\xff\xa3\x00\x77\x00\x00", b"\x00\xa4\x00\x77\x00\x00");
/// testcase(b"\xff\xff\xff\x77\x00\x00", b"\x00\x00\x00\x78\x00\x00");
/// ```
#[inline]
pub fn increment(v: &mut [u8]) {
let mut carry = 1u8;
for val in v.iter_mut() {
let (v, c) = black_box(*val).overflowing_add(black_box(carry));
*black_box(val) = v;
*black_box(&mut carry) = black_box(black_box(c) as u8);
}
}

17
constant-time/src/lib.rs Normal file
View File

@@ -0,0 +1,17 @@
//! constant-time implementations of some primitives
//!
//! Rosenpass internal library providing basic constant-time operations.
//!
//! ## TODO
//! Figure out methodology to ensure that code is actually constant time, see
//! <https://github.com/rosenpass/rosenpass/issues/232>
mod compare;
mod increment;
mod memcmp;
mod xor;
pub use compare::compare;
pub use increment::increment;
pub use memcmp::memcmp;
pub use xor::xor;

107
constant-time/src/memcmp.rs Normal file
View File

@@ -0,0 +1,107 @@
/// compares two sclices of memory content and returns whether they are equal
///
/// ## Leaks
/// If the two slices have differents lengths, the function will return immediately. This
/// effectively leaks the information whether the slices have equal length or not. This is widely
/// considered safe.
///
/// The execution time of the function grows approx. linear with the length of the input. This is
/// considered safe.
#[inline]
pub fn memcmp(a: &[u8], b: &[u8]) -> bool {
a.len() == b.len() && unsafe { memsec::memeq(a.as_ptr(), b.as_ptr(), a.len()) }
}
/// [tests::memcmp_runs_in_constant_time] runs a stasticial test that the equality of the two
/// input parameters does not correlate with the run time.
///
/// For discussion on how to (further) ensure the constant-time execution of this function,
/// see <https://github.com/rosenpass/rosenpass/issues/232>
#[cfg(all(test, feature = "constant_time_tests"))]
mod tests {
use super::*;
use rand::seq::SliceRandom;
use rand::thread_rng;
use std::time::Instant;
#[test]
/// tests whether [memcmp] actually runs in constant time
///
/// This test function will run an equal amount of comparisons on two different sets of parameters:
/// - completely equal slices
/// - completely unequal slices.
/// All comparisons are executed in a randomized order. The test will fail if one of the
/// two sets is checked for equality significantly faster than the other set
/// (absolute correlation coefficient ≥ 0.01)
fn memcmp_runs_in_constant_time() {
// prepare data to compare
let n: usize = 1E6 as usize; // number of comparisons to run
let len = 1024; // length of each slice passed as parameters to the tested comparison function
let a1 = "a".repeat(len);
let a2 = a1.clone();
let b = "b".repeat(len);
let a1 = a1.as_bytes();
let a2 = a2.as_bytes();
let b = b.as_bytes();
// vector representing all timing tests
//
// Each element is a tuple of:
// 0: whether the test compared two equal slices
// 1: the duration needed for the comparison to run
let mut tests = (0..n)
.map(|i| (i < n / 2, std::time::Duration::ZERO))
.collect::<Vec<_>>();
tests.shuffle(&mut thread_rng());
// run comparisons / call function to test
for test in tests.iter_mut() {
let now = Instant::now();
if test.0 {
memcmp(a1, a2);
} else {
memcmp(a1, b);
}
test.1 = now.elapsed();
// println!("eq: {}, elapsed: {:.2?}", test.0, test.1);
}
// sort by execution time and calculate Pearson correlation coefficient
tests.sort_by_key(|v| v.1);
let tests = tests
.iter()
.map(|t| (if t.0 { 1_f64 } else { 0_f64 }, t.1.as_nanos() as f64))
.collect::<Vec<_>>();
// averages
let (avg_x, avg_y): (f64, f64) = (
tests.iter().map(|t| t.0).sum::<f64>() / n as f64,
tests.iter().map(|t| t.1).sum::<f64>() / n as f64,
);
assert!((avg_x - 0.5).abs() < 1E-12);
// standard deviations
let sd_x = 0.5;
let sd_y = (1_f64 / n as f64
* tests
.iter()
.map(|t| {
let difference = t.1 - avg_y;
difference * difference
})
.sum::<f64>())
.sqrt();
// covariance
let cv = 1_f64 / n as f64
* tests
.iter()
.map(|t| (t.0 - avg_x) * (t.1 - avg_y))
.sum::<f64>();
// Pearson correlation
let correlation = cv / (sd_x * sd_y);
println!("correlation: {:.6?}", correlation);
assert!(
correlation.abs() < 0.01,
"execution time correlates with result"
)
}
}

34
constant-time/src/xor.rs Normal file
View File

@@ -0,0 +1,34 @@
use core::hint::black_box;
use rosenpass_to::{with_destination, To};
/// Xors the source into the destination
///
/// # Panics
/// If source and destination are of different sizes.
///
/// # Leaks
/// TODO: mention here if this function leaks any information, see
/// <https://github.com/rosenpass/rosenpass/issues/232>
///
/// ## Tests
/// For discussion on how to ensure the constant-time execution of this function, see
/// <https://github.com/rosenpass/rosenpass/issues/232>
///
/// # Examples
///
/// ```
/// use rosenpass_constant_time::xor;
/// use rosenpass_to::To;
/// assert_eq!(
/// xor(b"world").to_this(|| b"hello".to_vec()),
/// b"\x1f\n\x1e\x00\x0b");
/// ```
#[inline]
pub fn xor(src: &[u8]) -> impl To<[u8], ()> + '_ {
with_destination(|dst: &mut [u8]| {
assert!(black_box(src.len()) == black_box(dst.len()));
for (dv, sv) in dst.iter_mut().zip(src.iter()) {
*black_box(dv) ^= black_box(*sv);
}
})
}

13
doc/check.sh Executable file
View File

@@ -0,0 +1,13 @@
#!/usr/bin/env bash
# We have to filter this STYLE error out, because it is very platform specific
OUTPUT=$(mandoc -Tlint "$1" | grep --invert-match "STYLE: referenced manual not found")
if [ -z "$OUTPUT" ]
then
exit 0
else
echo "$1 is malformatted, check mandoc -Tlint $1"
echo "$OUTPUT"
exit 1
fi

View File

@@ -12,18 +12,18 @@
.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
and then 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.
practical in fewer 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>
.It Ar gen-keys --secret-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!
@@ -31,7 +31,7 @@ file secret!
Start a process to exchange keys with the specified peers.
You should specify at least one peer.
.Pp
It's
Its
.Ar OPTIONS
are as follows:
.Bl -tag -width Ds
@@ -39,7 +39,7 @@ are as follows:
Instructs
.Nm
to listen on the specified interface and port.
By default
By default,
.Nm
will listen on all interfaces and select a random port.
.It Ar verbose
@@ -91,15 +91,24 @@ This makes it possible to add peers entirely from
.Sh SEE ALSO
.Xr rp 1 ,
.Xr wg 1
.Rs
.%A Karolin Varner
.%A Benjamin Lipp
.%A Wanja Zaeske
.%A Lisa Schmidt
.%D 2023
.%T Rosenpass
.%U https://rosenpass.eu/whitepaper.pdf
.Re
.Sh STANDARDS
This tool is the reference implementation of the Rosenpass protocol, written
by Karolin Varner, Benjamin Lipp, Wanja Zaeske, and Lisa Schmidt.
This tool is the reference implementation of the Rosenpass protocol, as
specified within the whitepaper referenced above.
.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
.An Clara Engler
.Sh BUGS
The bugs are tracked at
.Lk https://github.com/rosenpass/rosenpass/issues .

View File

@@ -113,7 +113,7 @@ 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
.An Clara Engler
.Sh BUGS
The bugs are tracked at
.Lk https://github.com/rosenpass/rosenpass/issues .

51
flake.lock generated
View File

@@ -8,11 +8,11 @@
"rust-analyzer-src": "rust-analyzer-src"
},
"locked": {
"lastModified": 1692771621,
"narHash": "sha256-W1qOIeOvzkJxdITGGWqSxmFbu9ob+ZP8lXNkkQi8UL4=",
"lastModified": 1728282832,
"narHash": "sha256-I7AbcwGggf+CHqpyd/9PiAjpIBGTGx5woYHqtwxaV7I=",
"owner": "nix-community",
"repo": "fenix",
"rev": "add522038f2a32aa1263c8d3c81e1ea2265cc4e1",
"rev": "1ec71be1f4b8f3105c5d38da339cb061fefc43f4",
"type": "github"
},
"original": {
@@ -26,11 +26,11 @@
"systems": "systems"
},
"locked": {
"lastModified": 1689068808,
"narHash": "sha256-6ixXo3wt24N/melDWjq70UuHQLxGV8jZvooRanIHXw0=",
"lastModified": 1726560853,
"narHash": "sha256-X6rJYSESBVr3hBoH0WbKE5KvhPU5bloyZ2L4K60/fPQ=",
"owner": "numtide",
"repo": "flake-utils",
"rev": "919d646de7be200f3bf08cb76ae1f09402b6f9b4",
"rev": "c1dfcf08411b08f6b8615f7d8971a2bfa81d5e8a",
"type": "github"
},
"original": {
@@ -39,56 +39,37 @@
"type": "github"
}
},
"naersk": {
"inputs": {
"nixpkgs": [
"nixpkgs"
]
},
"locked": {
"lastModified": 1692351612,
"narHash": "sha256-KTGonidcdaLadRnv9KFgwSMh1ZbXoR/OBmPjeNMhFwU=",
"owner": "nix-community",
"repo": "naersk",
"rev": "78789c30d64dea2396c9da516bbcc8db3a475207",
"type": "github"
},
"original": {
"owner": "nix-community",
"repo": "naersk",
"type": "github"
}
},
"nixpkgs": {
"locked": {
"lastModified": 1691522891,
"narHash": "sha256-xqQqVryXKJoFQ/+RL0A7DihkLkev8dk6afM7B04TilU=",
"lastModified": 1728193676,
"narHash": "sha256-PbDWAIjKJdlVg+qQRhzdSor04bAPApDqIv2DofTyynk=",
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "78287547942dd8e8afff0ae47fb8e2553db79d7e",
"rev": "ecbc1ca8ffd6aea8372ad16be9ebbb39889e55b6",
"type": "github"
},
"original": {
"id": "nixpkgs",
"type": "indirect"
"owner": "NixOS",
"ref": "nixos-24.05",
"repo": "nixpkgs",
"type": "github"
}
},
"root": {
"inputs": {
"fenix": "fenix",
"flake-utils": "flake-utils",
"naersk": "naersk",
"nixpkgs": "nixpkgs"
}
},
"rust-analyzer-src": {
"flake": false,
"locked": {
"lastModified": 1692701491,
"narHash": "sha256-Lz5GXi/CImvcIXtpBpQ9jVI9Ni9eU/4xk36PvKmjwJM=",
"lastModified": 1728249780,
"narHash": "sha256-J269DvCI5dzBmPrXhAAtj566qt0b22TJtF3TIK+tMsI=",
"owner": "rust-lang",
"repo": "rust-analyzer",
"rev": "9e3bf69ad3c736893b285f47f4d014ae1aed1cb0",
"rev": "2b750da1a1a2c1d2c70896108d7096089842d877",
"type": "github"
},
"original": {

315
flake.nix
View File

@@ -1,11 +1,8 @@
{
inputs = {
nixpkgs.url = "github:NixOS/nixpkgs/nixos-24.05";
flake-utils.url = "github:numtide/flake-utils";
# for quicker rust builds
naersk.url = "github:nix-community/naersk";
naersk.inputs.nixpkgs.follows = "nixpkgs";
# for rust nightly with llvm-tools-preview
fenix.url = "github:nix-community/fenix";
fenix.inputs.nixpkgs.follows = "nixpkgs";
@@ -14,6 +11,15 @@
outputs = { self, nixpkgs, flake-utils, ... }@inputs:
nixpkgs.lib.foldl (a: b: nixpkgs.lib.recursiveUpdate a b) { } [
#
### Export the overlay.nix from this flake ###
#
{
overlays.default = import ./overlay.nix;
}
#
### Actual Rosenpass Package and Docker Container Images ###
#
@@ -29,210 +35,39 @@
]
(system:
let
lib = nixpkgs.lib;
# normal nixpkgs
pkgs = import nixpkgs {
inherit system;
# TODO remove overlay once a fix for
# https://github.com/NixOS/nixpkgs/issues/216904 got merged
overlays = [
(
final: prev: {
iproute2 = prev.iproute2.overrideAttrs (old:
let
isStatic = prev.stdenv.hostPlatform.isStatic;
in
{
makeFlags = old.makeFlags ++ prev.lib.optional isStatic [
"TC_CONFIG_NO_XT=y"
];
});
}
)
];
};
# parsed Cargo.toml
cargoToml = builtins.fromTOML (builtins.readFile ./Cargo.toml);
# source files relevant for rust
src = pkgs.lib.sourceByRegex ./. [
"Cargo\\.(toml|lock)"
"build.rs"
"(src|benches)(/.*\\.(rs|md))?"
"rp"
];
# builds a bin path for all dependencies for the `rp` shellscript
rpBinPath = p: with p; lib.makeBinPath [
coreutils
findutils
gawk
wireguard-tools
];
# a function to generate a nix derivation for rosenpass against any
# given set of nixpkgs
rpDerivation = p:
let
# whether we want to build a statically linked binary
isStatic = p.targetPlatform.isStatic;
# the rust target of `p`
target = p.rust.toRustTargetSpec p.targetPlatform;
# convert a string to shout case
shout = string: builtins.replaceStrings [ "-" ] [ "_" ] (pkgs.lib.toUpper string);
# suitable Rust toolchain
toolchain = with inputs.fenix.packages.${system}; combine [
stable.cargo
stable.rustc
targets.${target}.stable.rust-std
];
# naersk with a custom toolchain
naersk = pkgs.callPackage inputs.naersk {
cargo = toolchain;
rustc = toolchain;
};
# used to trick the build.rs into believing that CMake was ran **again**
fakecmake = pkgs.writeScriptBin "cmake" ''
#! ${pkgs.stdenv.shell} -e
true
'';
in
naersk.buildPackage
{
# metadata and source
name = cargoToml.package.name;
version = cargoToml.package.version;
inherit src;
doCheck = true;
nativeBuildInputs = with pkgs; [
p.stdenv.cc
cmake # for oqs build in the oqs-sys crate
mandoc # for the built-in manual
makeWrapper # for the rp shellscript
pkg-config # let libsodium-sys-stable find libsodium
removeReferencesTo
rustPlatform.bindgenHook # for C-bindings in the crypto libs
];
buildInputs = with p; [ bash libsodium ];
override = x: {
preBuild =
# nix defaults to building for aarch64 _without_ the armv8-a crypto
# extensions, but liboqs depens on these
(lib.optionalString (system == "aarch64-linux") ''
NIX_CFLAGS_COMPILE="$NIX_CFLAGS_COMPILE -march=armv8-a+crypto"
''
);
# fortify is only compatible with dynamic linking
hardeningDisable = lib.optional isStatic "fortify";
};
overrideMain = x: {
# CMake detects that it was served a _foreign_ target dir, and CMake
# would be executed again upon the second build step of naersk.
# By adding our specially optimized CMake version, we reduce the cost
# of recompilation by 99 % while, while avoiding any CMake errors.
nativeBuildInputs = [ (lib.hiPrio fakecmake) ] ++ x.nativeBuildInputs;
# make sure that libc is linked, under musl this is not the case per
# default
preBuild = (lib.optionalString isStatic ''
NIX_CFLAGS_COMPILE="$NIX_CFLAGS_COMPILE -lc"
'');
preInstall = ''
install -D ${./rp} $out/bin/rp
wrapProgram $out/bin/rp --prefix PATH : "${ rpBinPath p }"
'';
};
# 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_
RUST_MIN_STACK = 8 * 1024 * 1024; # 8 MiB
# We want to build for a specific target...
CARGO_BUILD_TARGET = target;
# ... which might require a non-default linker:
"CARGO_TARGET_${shout target}_LINKER" =
let
inherit (p.stdenv) cc;
in
"${cc}/bin/${cc.targetPrefix}cc";
meta = with pkgs.lib;
{
inherit (cargoToml.package) description homepage;
license = with licenses; [ mit asl20 ];
maintainers = [ maintainers.wucke13 ];
platforms = platforms.all;
};
} // (lib.mkIf isStatic {
# otherwise pkg-config tries to link non-existent dynamic libs
# documented here: https://docs.rs/pkg-config/latest/pkg_config/
PKG_CONFIG_ALL_STATIC = true;
# tell rust to build everything statically linked
CARGO_BUILD_RUSTFLAGS = "-C target-feature=+crt-static";
});
# a function to generate a docker image based of rosenpass
rosenpassOCI = name: pkgs.dockerTools.buildImage rec {
inherit name;
copyToRoot = pkgs.buildEnv {
name = "image-root";
paths = [ self.packages.${system}.${name} ];
pathsToLink = [ "/bin" ];
};
config.Cmd = [ "/bin/rosenpass" ];
# apply our own overlay, overriding/inserting our packages as defined in ./pkgs
overlays = [ self.overlays.default ];
};
in
rec {
packages = rec {
default = rosenpass;
rosenpass = rpDerivation pkgs;
rosenpass-oci-image = rosenpassOCI "rosenpass";
{
packages = {
default = pkgs.rosenpass;
rosenpass = pkgs.rosenpass;
rosenpass-oci-image = pkgs.rosenpass-oci-image;
rp = pkgs.rp;
# derivation for the release
release-package =
let
version = cargoToml.package.version;
package =
if pkgs.hostPlatform.isLinux then
packages.rosenpass-static
else packages.rosenpass;
oci-image =
if pkgs.hostPlatform.isLinux then
packages.rosenpass-static-oci-image
else packages.rosenpass-oci-image;
in
pkgs.runCommandNoCC "lace-result" { }
''
mkdir {bin,$out}
cp ${./.}/rp bin/
tar -cvf $out/rosenpass-${system}-${version}.tar bin/rp \
-C ${package} bin/rosenpass
cp ${oci-image} \
$out/rosenpass-oci-image-${system}-${version}.tar.gz
'';
} // (if pkgs.stdenv.isLinux then rec {
rosenpass-static = rpDerivation pkgs.pkgsStatic;
rosenpass-static-oci-image = rosenpassOCI "rosenpass-static";
} else { });
release-package = pkgs.release-package;
# for good measure, we also offer to cross compile to Linux on Arm
aarch64-linux-rosenpass-static =
pkgs.pkgsCross.aarch64-multiplatform.pkgsStatic.rosenpass;
aarch64-linux-rp-static = pkgs.pkgsCross.aarch64-multiplatform.pkgsStatic.rp;
}
//
# We only offer static builds for linux, as this is not supported on OS X
(nixpkgs.lib.attrsets.optionalAttrs pkgs.stdenv.isLinux {
rosenpass-static = pkgs.pkgsStatic.rosenpass;
rosenpass-static-oci-image = pkgs.pkgsStatic.rosenpass-oci-image;
rp-static = pkgs.pkgsStatic.rp;
});
}
))
#
### Linux specifics ###
#
@@ -240,97 +75,53 @@
let
pkgs = import nixpkgs {
inherit system;
# apply our own overlay, overriding/inserting our packages as defined in ./pkgs
overlays = [ self.overlays.default ];
};
packages = self.packages.${system};
in
{
#
### Whitepaper ###
#
packages.whitepaper =
let
tlsetup = (pkgs.texlive.combine {
inherit (pkgs.texlive) scheme-basic acmart amsfonts ccicons
csquotes csvsimple doclicense fancyvrb fontspec gobble
koma-script ifmtarg latexmk lm markdown mathtools minted noto
nunito pgf soul unicode-math lualatex-math paralist
gitinfo2 eso-pic biblatex biblatex-trad biblatex-software
xkeyval xurl xifthen biber;
});
in
pkgs.stdenvNoCC.mkDerivation {
name = "whitepaper";
src = ./papers;
nativeBuildInputs = with pkgs; [
ncurses # tput
python3Packages.pygments
tlsetup # custom tex live scheme
which
];
buildPhase = ''
export HOME=$(mktemp -d)
export OSFONTDIR="$(kpsewhich --var-value TEXMF)/fonts/{opentype/public/nunito,truetype/google/noto}"
latexmk -r tex/CI.rc
'';
installPhase = ''
mkdir -p $out
mv *.pdf readme.md $out/
'';
};
#
### Reading materials ###
#
packages.whitepaper = pkgs.whitepaper;
#
### Proof and Proof Tools ###
#
packages.proverif-patched = pkgs.proverif.overrideAttrs (old: {
postInstall = ''
install -D -t $out/lib cryptoverif.pvl
'';
});
packages.proof-proverif = pkgs.stdenv.mkDerivation {
name = "rosenpass-proverif-proof";
version = "unstable";
src = pkgs.lib.sourceByRegex ./. [
"analyze.sh"
"marzipan(/marzipan.awk)?"
"analysis(/.*)?"
];
nativeBuildInputs = [ pkgs.proverif pkgs.graphviz ];
CRYPTOVERIF_LIB = packages.proverif-patched + "/lib/cryptoverif.pvl";
installPhase = ''
mkdir -p $out
bash analyze.sh -color -html $out
'';
};
packages.proverif-patched = pkgs.proverif-patched;
packages.proof-proverif = pkgs.proof-proverif;
#
### Devshells ###
#
devShells.default = pkgs.mkShell {
inherit (packages.proof-proverif) CRYPTOVERIF_LIB;
inherit (packages.rosenpass) RUST_MIN_STACK;
inputsFrom = [ packages.default ];
inherit (pkgs.proof-proverif) CRYPTOVERIF_LIB;
inputsFrom = [ pkgs.rosenpass ];
nativeBuildInputs = with pkgs; [
cmake # override the fakecmake from the main step above
cargo-release
clippy
nodePackages.prettier
rustfmt
packages.proverif-patched
nodePackages.prettier
nushell # for the .ci/gen-workflow-files.nu script
proverif-patched
];
};
devShells.coverage = pkgs.mkShell {
inputsFrom = [ packages.default ];
inherit (packages.rosenpass) RUST_MIN_STACK;
nativeBuildInputs = with pkgs; [ inputs.fenix.packages.${system}.complete.toolchain cargo-llvm-cov ];
inputsFrom = [ pkgs.rosenpass ];
nativeBuildInputs = [
inputs.fenix.packages.${system}.complete.toolchain
pkgs.cargo-llvm-cov
];
};
checks = {
cargo-fmt = pkgs.runCommand "check-cargo-fmt"
{ inherit (self.devShells.${system}.default) nativeBuildInputs buildInputs; } ''
cargo fmt --manifest-path=${./.}/Cargo.toml --check && touch $out
cargo fmt --manifest-path=${./.}/Cargo.toml --check --all && touch $out
'';
nixpkgs-fmt = pkgs.runCommand "check-nixpkgs-fmt"
{ nativeBuildInputs = [ pkgs.nixpkgs-fmt ]; } ''

115
format_rust_code.sh Executable file
View File

@@ -0,0 +1,115 @@
#!/usr/bin/env bash
# Parse command line options
while [[ $# -gt 0 ]]; do
case "$1" in
--mode)
mode="$2"
shift 2
;;
*)
echo "Unknown option: $1"
exit 1
;;
esac
done
# Check if mode is specified
if [ -z "$mode" ]; then
echo "Please specify the mode using --mode option. Valid modes are 'check' and 'fix'."
exit 1
fi
# Find all Markdown files in the current directory and its subdirectories
mapfile -t md_files < <(find . -type f -name "*.md")
count=0
# Iterate through each Markdown file
for file in "${md_files[@]}"; do
# Use awk to extract Rust code blocks enclosed within triple backticks
rust_code_blocks=$(awk '/```rust/{flag=1; next}/```/{flag=0} flag' "$file")
# Count the number of Rust code blocks
num_fences=$(awk '/```rust/{f=1} f{if(/```/){f=0; count++}} END{print count}' "$file")
if [ -n "$rust_code_blocks" ]; then
echo "Processing Rust code in $file"
# Iterate through each Rust code block
for ((i=1; i <= num_fences ; i++)); do
# Extract individual Rust code block using awk
current_rust_block=$(awk -v i="$i" '/```rust/{f=1; if (++count == i) next} f&&/```/{f=0;next} f' "$file")
# Variable to check if we have added the main function
add_main=0
# Check if the Rust code block is already inside a function
if ! echo "$current_rust_block" | grep -q "fn main()"; then
# If not, wrap it in a main function
current_rust_block=$'fn main() {\n'"$current_rust_block"$'\n}'
add_main=1
fi
if [ "$mode" == "check" ]; then
# Apply changes to the Rust code block
formatted_rust_code=$(echo "$current_rust_block" | rustfmt)
# Use rustfmt to format the Rust code block, remove first and last lines, and remove the first 4 spaces if added main function
if [ "$add_main" == 1 ]; then
formatted_rust_code=$(echo "$formatted_rust_code" | sed '1d;$d' | sed 's/^ //')
current_rust_block=$(echo "$current_rust_block" | sed '1d;')
current_rust_block=$(echo "$current_rust_block" | sed '$d')
fi
if [ "$formatted_rust_code" == "$current_rust_block" ]; then
echo "No changes needed in Rust code block $i in $file"
else
echo -e "\nChanges needed in Rust code block $i in $file:\n"
echo "$formatted_rust_code"
count=+1
fi
elif [ "$mode" == "fix" ]; then
# Replace current_rust_block with formatted_rust_code in the file
formatted_rust_code=$(echo "$current_rust_block" | rustfmt)
# Use rustfmt to format the Rust code block, remove first and last lines, and remove the first 4 spaces if added main function
if [ "$add_main" == 1 ]; then
formatted_rust_code=$(echo "$formatted_rust_code" | sed '1d;$d' | sed 's/^ //')
current_rust_block=$(echo "$current_rust_block" | sed '1d;')
current_rust_block=$(echo "$current_rust_block" | sed '$d')
fi
# Check if the formatted code is the same as the current Rust code block
if [ "$formatted_rust_code" == "$current_rust_block" ]; then
echo "No changes needed in Rust code block $i in $file"
else
echo "Formatting Rust code block $i in $file"
# Replace current_rust_block with formatted_rust_code in the file
# Use awk to find the line number of the pattern
start_line=$(grep -n "^\`\`\`rust" "$file" | sed -n "${i}p" | cut -d: -f1)
end_line=$(grep -n "^\`\`\`" "$file" | awk -F: -v start_line="$start_line" '$1 > start_line {print $1; exit;}')
if [ -n "$start_line" ] && [ -n "$end_line" ]; then
# Print lines before the Rust code block
head -n "$((start_line - 1))" "$file"
# Print the formatted Rust code block
echo "\`\`\`rust"
echo "$formatted_rust_code"
echo "\`\`\`"
# Print lines after the Rust code block
tail -n +"$((end_line + 1))" "$file"
else
# Rust code block not found or end line not found
cat "$file"
fi > tmpfile && mv tmpfile "$file"
fi
else
echo "Unknown mode: $mode. Valid modes are 'check' and 'fix'."
exit 1
fi
done
fi
done
# CI failure if changes are needed
if [ $count -gt 0 ]; then
echo "CI failed: Changes needed in Rust code blocks."
exit 1
fi

4
fuzz/.gitignore vendored Normal file
View File

@@ -0,0 +1,4 @@
target
corpus
artifacts
coverage

1286
fuzz/Cargo.lock generated Normal file

File diff suppressed because it is too large Load Diff

87
fuzz/Cargo.toml Normal file
View File

@@ -0,0 +1,87 @@
[package]
name = "rosenpass-fuzzing"
version = "0.0.1"
publish = false
edition = "2021"
[features]
experiment_libcrux = ["rosenpass-ciphers/experiment_libcrux"]
[package.metadata]
cargo-fuzz = true
[dependencies]
arbitrary = { workspace = true }
libfuzzer-sys = { workspace = true }
stacker = { workspace = true }
rosenpass-secret-memory = { workspace = true }
rosenpass-ciphers = { workspace = true }
rosenpass-cipher-traits = { workspace = true }
rosenpass-to = { workspace = true }
rosenpass = { workspace = true }
[[bin]]
name = "fuzz_handle_msg"
path = "fuzz_targets/handle_msg.rs"
test = false
doc = false
[[bin]]
name = "fuzz_blake2b"
path = "fuzz_targets/blake2b.rs"
test = false
doc = false
[[bin]]
name = "fuzz_aead_enc_into"
path = "fuzz_targets/aead_enc_into.rs"
test = false
doc = false
[[bin]]
name = "fuzz_mceliece_encaps"
path = "fuzz_targets/mceliece_encaps.rs"
test = false
doc = false
[[bin]]
name = "fuzz_kyber_encaps"
path = "fuzz_targets/kyber_encaps.rs"
test = false
doc = false
[[bin]]
name = "fuzz_box_secret_alloc_malloc"
path = "fuzz_targets/box_secret_alloc_malloc.rs"
test = false
doc = false
[[bin]]
name = "fuzz_vec_secret_alloc_malloc"
path = "fuzz_targets/vec_secret_alloc_malloc.rs"
test = false
doc = false
[[bin]]
name = "fuzz_box_secret_alloc_memfdsec"
path = "fuzz_targets/box_secret_alloc_memfdsec.rs"
test = false
doc = false
[[bin]]
name = "fuzz_vec_secret_alloc_memfdsec"
path = "fuzz_targets/vec_secret_alloc_memfdsec.rs"
test = false
doc = false
[[bin]]
name = "fuzz_box_secret_alloc_memfdsec_mallocfb"
path = "fuzz_targets/box_secret_alloc_memfdsec_mallocfb.rs"
test = false
doc = false
[[bin]]
name = "fuzz_vec_secret_alloc_memfdsec_mallocfb"
path = "fuzz_targets/vec_secret_alloc_memfdsec_mallocfb.rs"
test = false
doc = false

View File

@@ -0,0 +1,28 @@
#![no_main]
extern crate arbitrary;
extern crate rosenpass;
use libfuzzer_sys::fuzz_target;
use rosenpass_ciphers::aead;
#[derive(arbitrary::Arbitrary, Debug)]
pub struct Input {
pub key: [u8; 32],
pub nonce: [u8; 12],
pub ad: Box<[u8]>,
pub plaintext: Box<[u8]>,
}
fuzz_target!(|input: Input| {
let mut ciphertext = vec![0u8; input.plaintext.len() + 16];
aead::encrypt(
ciphertext.as_mut_slice(),
&input.key,
&input.nonce,
&input.ad,
&input.plaintext,
)
.unwrap();
});

View File

@@ -0,0 +1,20 @@
#![no_main]
extern crate arbitrary;
extern crate rosenpass;
use libfuzzer_sys::fuzz_target;
use rosenpass_ciphers::subtle::blake2b;
use rosenpass_to::To;
#[derive(arbitrary::Arbitrary, Debug)]
pub struct Blake2b {
pub key: [u8; 32],
pub data: Box<[u8]>,
}
fuzz_target!(|input: Blake2b| {
let mut out = [0u8; 32];
blake2b::hash(&input.key, &input.data).to(&mut out).unwrap();
});

View File

@@ -0,0 +1,12 @@
#![no_main]
use libfuzzer_sys::fuzz_target;
use rosenpass_secret_memory::alloc::secret_box;
use rosenpass_secret_memory::policy::*;
use std::sync::Once;
static ONCE: Once = Once::new();
fuzz_target!(|data: &[u8]| {
ONCE.call_once(secret_policy_use_only_malloc_secrets);
let _ = secret_box(data);
});

View File

@@ -0,0 +1,13 @@
#![no_main]
use libfuzzer_sys::fuzz_target;
use rosenpass_secret_memory::alloc::secret_box;
use rosenpass_secret_memory::policy::*;
use std::sync::Once;
static ONCE: Once = Once::new();
fuzz_target!(|data: &[u8]| {
ONCE.call_once(secret_policy_use_only_memfd_secrets);
let _ = secret_box(data);
});

View File

@@ -0,0 +1,13 @@
#![no_main]
use libfuzzer_sys::fuzz_target;
use rosenpass_secret_memory::alloc::secret_box;
use rosenpass_secret_memory::policy::*;
use std::sync::Once;
static ONCE: Once = Once::new();
fuzz_target!(|data: &[u8]| {
ONCE.call_once(secret_policy_try_use_memfd_secrets);
let _ = secret_box(data);
});

View File

@@ -0,0 +1,24 @@
#![no_main]
extern crate rosenpass;
use libfuzzer_sys::fuzz_target;
use rosenpass::protocol::CryptoServer;
use rosenpass_cipher_traits::Kem;
use rosenpass_ciphers::kem::StaticKem;
use rosenpass_secret_memory::policy::*;
use rosenpass_secret_memory::{PublicBox, Secret};
use std::sync::Once;
static ONCE: Once = Once::new();
fuzz_target!(|rx_buf: &[u8]| {
ONCE.call_once(secret_policy_use_only_malloc_secrets);
let sk = Secret::from_slice(&[0; StaticKem::SK_LEN]);
let pk = PublicBox::from_slice(&[0; StaticKem::PK_LEN]);
let mut cs = CryptoServer::new(sk, pk);
let mut tx_buf = [0; 10240];
// We expect errors while fuzzing therefore we do not check the result.
let _ = cs.handle_msg(rx_buf, &mut tx_buf);
});

View File

@@ -0,0 +1,20 @@
#![no_main]
extern crate arbitrary;
extern crate rosenpass;
use libfuzzer_sys::fuzz_target;
use rosenpass_cipher_traits::Kem;
use rosenpass_ciphers::kem::EphemeralKem;
#[derive(arbitrary::Arbitrary, Debug)]
pub struct Input {
pub pk: [u8; EphemeralKem::PK_LEN],
}
fuzz_target!(|input: Input| {
let mut ciphertext = [0u8; EphemeralKem::CT_LEN];
let mut shared_secret = [0u8; EphemeralKem::SHK_LEN];
EphemeralKem::encaps(&mut shared_secret, &mut ciphertext, &input.pk).unwrap();
});

View File

@@ -0,0 +1,15 @@
#![no_main]
extern crate rosenpass;
use libfuzzer_sys::fuzz_target;
use rosenpass_cipher_traits::Kem;
use rosenpass_ciphers::kem::StaticKem;
fuzz_target!(|input: [u8; StaticKem::PK_LEN]| {
let mut ciphertext = [0u8; StaticKem::CT_LEN];
let mut shared_secret = [0u8; StaticKem::SHK_LEN];
// We expect errors while fuzzing therefore we do not check the result.
let _ = StaticKem::encaps(&mut shared_secret, &mut ciphertext, &input);
});

View File

@@ -0,0 +1,15 @@
#![no_main]
use std::sync::Once;
use libfuzzer_sys::fuzz_target;
use rosenpass_secret_memory::alloc::secret_vec;
use rosenpass_secret_memory::policy::*;
static ONCE: Once = Once::new();
fuzz_target!(|data: &[u8]| {
ONCE.call_once(secret_policy_use_only_malloc_secrets);
let mut vec = secret_vec();
vec.extend_from_slice(data);
});

View File

@@ -0,0 +1,15 @@
#![no_main]
use std::sync::Once;
use libfuzzer_sys::fuzz_target;
use rosenpass_secret_memory::alloc::secret_vec;
use rosenpass_secret_memory::policy::*;
static ONCE: Once = Once::new();
fuzz_target!(|data: &[u8]| {
ONCE.call_once(secret_policy_use_only_memfd_secrets);
let mut vec = secret_vec();
vec.extend_from_slice(data);
});

View File

@@ -0,0 +1,15 @@
#![no_main]
use std::sync::Once;
use libfuzzer_sys::fuzz_target;
use rosenpass_secret_memory::alloc::secret_vec;
use rosenpass_secret_memory::policy::*;
static ONCE: Once = Once::new();
fuzz_target!(|data: &[u8]| {
ONCE.call_once(secret_policy_try_use_memfd_secrets);
let mut vec = secret_vec();
vec.extend_from_slice(data);
});

View File

@@ -0,0 +1,13 @@
secret_key = "peer_a.rp.sk"
public_key = "peer_a.rp.pk"
listen = ["[::1]:46127"]
verbosity = "Verbose"
[api]
listen_path = []
listen_fd = []
stream_fd = []
[[peers]]
public_key = "peer_b.rp.pk"
device = "rpPskBrkTestA"

View File

@@ -0,0 +1,14 @@
secret_key = "peer_b.rp.sk"
public_key = "peer_b.rp.pk"
listen = []
verbosity = "Verbose"
[api]
listen_path = []
listen_fd = []
stream_fd = []
[[peers]]
public_key = "peer_a.rp.pk"
endpoint = "[::1]:46127"
device = "rpPskBrkTestB"

View File

@@ -0,0 +1,215 @@
#! /bin/bash
set -e -o pipefail
enquote() {
while (( "$#" > 1)); do
printf "%q " "$1"
shift
done
if (("$#" > 0)); then
printf "%q" "$1"
fi
}
CLEANUP_HOOKS=()
hook_cleanup() {
local hook
set +e +o pipefail
for hook in "${CLEANUP_HOOKS[@]}"; do
eval "${hook}"
done
}
cleanup() {
CLEANUP_HOOKS=("$(enquote exc_with_ctx cleanup "$@")" "${CLEANUP_HOOKS[@]}")
}
cleanup_eval() {
cleanup eval "$*"
}
stderr() {
echo >&2 "$@"
}
log() {
local level; level="$1"; shift || fatal "USAGE: log LVL MESSAGE.."
stderr "[${level}]" "$@"
}
info() {
log "INFO" "$@"
}
debug() {
log "DEBUG" "$@"
}
fatal() {
log "FATAL" "$@"
exit 1
}
assert() {
local msg; msg="$1"; shift || fatal "USAGE: assert_cmd MESSAGE COMMAND.."
"$@" || fatal "${msg}"
}
abs_dir() {
local dir; dir="$1"; shift || fatal "USAGE: abs_dir DIR"
(
cd "${dir}"
pwd -P
)
}
exc_with_ctx() {
local ctx; ctx="$1"; shift || fatal "USAGE: exc_with_ctx CONTEXT COMMAND.."
if [[ -z "${ctx}" ]]; then
info '$' "$@"
else
info "${ctx}\$" "$@"
fi
"$@"
}
exc() {
exc_with_ctx "" "$@"
}
exc_eval() {
exc eval "$*"
}
exc_eval_with_ctx() {
local ctx; ctx="$1"; shift || fatal "USAGE: exc_eval_with_ctx CONTEXT EVAL_COMMAND.."
exc_with_ctx "eval:${ctx}" "$*"
}
exc_as_user() {
exc sudo -u "${SUDO_USER}" "$@"
}
exc_eval_as_user() {
exc_as_user bash -c "$*"
}
fork_eval_as_user() {
exc sudo -u "${SUDO_USER}" bash -c "$*" &
local pid; pid="$!"
cleanup wait "${pid}"
cleanup pkill -2 -P "${pid}" # Reverse ordering
}
info_success() {
stderr
stderr
if [[ "${SUCCESS}" = 1 ]]; then
stderr " Test was a success!"
else
stderr " !!! TEST WAS A FAILURE!!!"
fi
stderr
}
main() {
assert "Use as root with sudo" [ "$(id -u)" -eq 0 ]
assert "Use as root with sudo" [ -n "${SUDO_UID}" ]
assert "SUDO_UID is 0; refusing to build as root" [ "${SUDO_UID}" -ne 0 ]
cleanup info_success
trap hook_cleanup EXIT
SCRIPT="$0"
CFG_TEMPLATE_DIR="$(abs_dir "$(dirname "${SCRIPT}")")"
REPO="$(abs_dir "${CFG_TEMPLATE_DIR}/../..")"
BINS="${REPO}/target/debug"
# Create temp dir
TMP_DIR="/tmp/rosenpass-psk-broker-test-$(date +%s)-$(uuidgen)"
cleanup rm -rf "${TMP_DIR}"
exc_as_user mkdir -p "${TMP_DIR}"
# Copy config
CFG_DIR="${TMP_DIR}/cfg"
exc_as_user cp -R "${CFG_TEMPLATE_DIR}" "${CFG_DIR}"
exc umask 077
exc cd "${REPO}"
local build_cmd; build_cmd=(cargo build --workspace --color=always --all-features --bins --profile dev)
if test -e "${BINS}/rosenpass-wireguard-broker-privileged" -a -e "${BINS}/rosenpass"; then
info "Found the binaries rosenpass-wireguard-broker-privileged and rosenpass." \
"Run following commands as a regular user to recompile the binaries with the right options" \
"in case of an error:" '$' "${build_cmd[@]}"
else
exc_as_user "${build_cmd[@]}"
fi
exc sudo setcap CAP_NET_ADMIN=+eip "${BINS}/rosenpass-wireguard-broker-privileged"
exc cd "${CFG_DIR}"
exc_eval_as_user "wg genkey > peer_a.wg.sk"
exc_eval_as_user "wg pubkey < peer_a.wg.sk > peer_a.wg.pk"
exc_eval_as_user "wg genkey > peer_b.wg.sk"
exc_eval_as_user "wg pubkey < peer_b.wg.sk > peer_b.wg.pk"
exc_eval_as_user "wg genpsk > peer_a_invalid.psk"
exc_eval_as_user "wg genpsk > peer_b_invalid.psk"
exc_eval_as_user "echo $(enquote "peer = \"$(cat peer_b.wg.pk)\"") >> peer_a.rp.config"
exc_eval_as_user "echo $(enquote "peer = \"$(cat peer_a.wg.pk)\"") >> peer_b.rp.config"
exc_as_user "${BINS}"/rosenpass gen-keys peer_a.rp.config
exc_as_user "${BINS}"/rosenpass gen-keys peer_b.rp.config
cleanup ip l del dev rpPskBrkTestA
cleanup ip l del dev rpPskBrkTestB
exc ip l add dev rpPskBrkTestA type wireguard
exc ip l add dev rpPskBrkTestB type wireguard
exc wg set rpPskBrkTestA \
listen-port 46125 \
private-key peer_a.wg.sk \
peer "$(cat peer_b.wg.pk)" \
endpoint 'localhost:46126' \
preshared-key peer_a_invalid.psk \
allowed-ips fe80::2/64
exc wg set rpPskBrkTestB \
listen-port 46126 \
private-key peer_b.wg.sk \
peer "$(cat peer_a.wg.pk)" \
endpoint 'localhost:46125' \
preshared-key peer_b_invalid.psk \
allowed-ips fe80::1/64
exc ip l set rpPskBrkTestA up
exc ip l set rpPskBrkTestB up
exc ip a add fe80::1/64 dev rpPskBrkTestA
exc ip a add fe80::2/64 dev rpPskBrkTestB
fork_eval_as_user "\
RUST_LOG='info' \
PATH=$(enquote "${REPO}/target/debug:${PATH}") \
$(enquote "${BINS}/rosenpass") --psk-broker-spawn \
exchange-config peer_a.rp.config"
fork_eval_as_user "\
RUST_LOG='info' \
PATH=$(enquote "${REPO}/target/debug:${PATH}") \
$(enquote "${BINS}/rosenpass-wireguard-broker-socket-handler") \
--listen-path broker.sock"
fork_eval_as_user "\
RUST_LOG='info' \
PATH=$(enquote "$PWD/target/debug:${PATH}") \
$(enquote "${BINS}/rosenpass") --psk-broker-path broker.sock \
exchange-config peer_b.rp.config"
exc_as_user ping -c 2 -w 10 fe80::1%rpPskBrkTestA
exc_as_user ping -c 2 -w 10 fe80::2%rpPskBrkTestB
exc_as_user ping -c 2 -w 10 fe80::2%rpPskBrkTestA
exc_as_user ping -c 2 -w 10 fe80::1%rpPskBrkTestB
SUCCESS=1
}
main "$@"

40
misc/README.md Normal file
View File

@@ -0,0 +1,40 @@
# Additional files
This folder contains additional files that are used in the project.
## `generate_configs.py`
The script is used to generate configuration files for a benchmark setup
consisting of a device under testing (DUT) and automatic test equipment (ATE),
basically a strong machine capable of running multiple Rosenpass instances at
once.
At the top of the script multiple variables can be set to configure the DUT IP
address and more. Once configured you may run `python3 generate_configs.py` to
create the configuration files.
A new folder called `output/` is created containing the subfolder `dut/` and
`ate/`. The former has to be copied on the DUT, ideally reproducible hardware
like a Raspberry Pi, while the latter is copied to the ATE, i.e. a laptop.
### Running a benchmark
On the ATE a run script is required since multiple instances of `rosenpass` are
started with different configurations in parallel. The scripts are named after
the number of instances they start, e.g. `run-50.sh` starts 50 instances.
```shell
# on the ATE aka laptop
cd output/ate
./run-10.sh
```
On the DUT you start a single Rosenpass instance with the configuration matching
the ATE number of peers.
```shell
# on the DUT aka Raspberry Pi
rosenpass exchange-config configs/dut-10.toml
```
Use whatever measurement tool you like to monitor the DUT and ATE.

105
misc/generate_configs.py Normal file
View File

@@ -0,0 +1,105 @@
from pathlib import Path
from subprocess import run
import os
config = dict(
peer_counts=[1, 5, 10, 50, 100, 500],
peer_count_max=100,
ate_ip="127.0.0.1",
dut_ip="127.0.0.1",
dut_port=9999,
path_to_rosenpass_bin=os.getcwd() + "/target/release/rosenpass",
)
print(config)
output_dir = Path("output")
output_dir.mkdir(exist_ok=True)
template_dut = """
public_key = "keys/dut-public-key"
secret_key = "keys/dut-secret-key"
listen = ["{dut_ip}:{dut_port}"]
verbosity = "Quiet"
"""
template_dut_peer = """
[[peers]] # ATE-{i}
public_key = "keys/ate-{i}-public-key"
endpoint = "{ate_ip}:{ate_port}"
key_out = "out/key_out_{i}"
"""
template_ate = """
public_key = "keys/ate-{i}-public-key"
secret_key = "keys/ate-{i}-secret-key"
listen = ["{ate_ip}:{ate_port}"]
verbosity = "Quiet"
[[peers]] # DUT
public_key = "keys/dut-public-key"
endpoint = "{dut_ip}:{dut_port}"
key_out = "out/key_out_{i}"
"""
(output_dir / "dut" / "keys").mkdir(exist_ok=True, parents=True)
(output_dir / "dut" / "out").mkdir(exist_ok=True, parents=True)
(output_dir / "dut" / "configs").mkdir(exist_ok=True, parents=True)
(output_dir / "ate" / "keys").mkdir(exist_ok=True, parents=True)
(output_dir / "ate" / "out").mkdir(exist_ok=True, parents=True)
(output_dir / "ate" / "configs").mkdir(exist_ok=True, parents=True)
for peer_count in config["peer_counts"]:
dut_config = template_dut.format(**config)
for i in range(peer_count):
dut_config += template_dut_peer.format(**config, i=i, ate_port=50000 + i)
(output_dir / "dut" / "configs" / f"dut-{peer_count}.toml").write_text(dut_config)
if not (output_dir / "dut" / "keys" / "dut-public-key").exists():
print("Generate DUT keys")
run(
[
config["path_to_rosenpass_bin"],
"gen-keys",
f"configs/dut-{peer_count}.toml",
],
cwd=output_dir / "dut",
)
else:
print("DUT keys already exist")
# copy the DUT public key to the ATE
(output_dir / "ate" / "keys" / "dut-public-key").write_bytes(
(output_dir / "dut" / "keys" / "dut-public-key").read_bytes()
)
ate_script = "(trap 'kill 0' SIGINT; \\\n"
for i in range(config["peer_count_max"]):
(output_dir / "ate" / "configs" / f"ate-{i}.toml").write_text(
template_ate.format(**config, i=i, ate_port=50000 + i)
)
if not (output_dir / "ate" / "keys" / f"ate-{i}-public-key").exists():
# generate ATE keys
run(
[config["path_to_rosenpass_bin"], "gen-keys", f"configs/ate-{i}.toml"],
cwd=output_dir / "ate",
)
else:
print(f"ATE-{i} keys already exist")
# copy the ATE public keys to the DUT
(output_dir / "dut" / "keys" / f"ate-{i}-public-key").write_bytes(
(output_dir / "ate" / "keys" / f"ate-{i}-public-key").read_bytes()
)
ate_script += (
f"{config['path_to_rosenpass_bin']} exchange-config configs/ate-{i}.toml & \\\n"
)
if (i + 1) in config["peer_counts"]:
write_script = ate_script
write_script += "wait)"
(output_dir / "ate" / f"run-{i+1}.sh").write_text(write_script)

16
oqs/Cargo.toml Normal file
View File

@@ -0,0 +1,16 @@
[package]
name = "rosenpass-oqs"
authors = ["Karolin Varner <karo@cupdev.net>", "wucke13 <wucke13@gmail.com>"]
version = "0.1.0"
edition = "2021"
license = "MIT OR Apache-2.0"
description = "Rosenpass internal bindings to liboqs"
homepage = "https://rosenpass.eu/"
repository = "https://github.com/rosenpass/rosenpass"
readme = "readme.md"
[dependencies]
rosenpass-cipher-traits = { workspace = true }
rosenpass-util = { workspace = true }
oqs-sys = { workspace = true }
paste = { workspace = true }

5
oqs/readme.md Normal file
View File

@@ -0,0 +1,5 @@
# Rosenpass internal liboqs bindings
Rosenpass internal library providing bindings to liboqs.
This is an internal library; not guarantee is made about its API at this point in time.

80
oqs/src/kem_macro.rs Normal file
View File

@@ -0,0 +1,80 @@
macro_rules! oqs_kem {
($name:ident) => { ::paste::paste!{
mod [< $name:snake >] {
use rosenpass_cipher_traits::Kem;
use rosenpass_util::result::Guaranteed;
pub enum [< $name:camel >] {}
/// # Panic & Safety
///
/// This Trait impl calls unsafe [oqs_sys] functions, that write to byte
/// slices only identified using raw pointers. It must be ensured that the raw
/// pointers point into byte slices of sufficient length, to avoid UB through
/// overwriting of arbitrary data. This is ensured through assertions in the
/// implementation.
///
/// __Note__: This requirement is stricter than necessary, it would suffice
/// to only check that the buffers are big enough, allowing them to be even
/// bigger. However, from a correctness point of view it does not make sense to
/// allow bigger buffers.
impl Kem for [< $name:camel >] {
type Error = ::std::convert::Infallible;
const SK_LEN: usize = ::oqs_sys::kem::[<OQS_KEM _ $name:snake _ length_secret_key >] as usize;
const PK_LEN: usize = ::oqs_sys::kem::[<OQS_KEM _ $name:snake _ length_public_key >] as usize;
const CT_LEN: usize = ::oqs_sys::kem::[<OQS_KEM _ $name:snake _ length_ciphertext >] as usize;
const SHK_LEN: usize = ::oqs_sys::kem::[<OQS_KEM _ $name:snake _ length_shared_secret >] as usize;
fn keygen(sk: &mut [u8], pk: &mut [u8]) -> Guaranteed<()> {
assert_eq!(sk.len(), Self::SK_LEN);
assert_eq!(pk.len(), Self::PK_LEN);
unsafe {
oqs_call!(
::oqs_sys::kem::[< OQS_KEM _ $name:snake _ keypair >],
pk.as_mut_ptr(),
sk.as_mut_ptr()
);
}
Ok(())
}
fn encaps(shk: &mut [u8], ct: &mut [u8], pk: &[u8]) -> Guaranteed<()> {
assert_eq!(shk.len(), Self::SHK_LEN);
assert_eq!(ct.len(), Self::CT_LEN);
assert_eq!(pk.len(), Self::PK_LEN);
unsafe {
oqs_call!(
::oqs_sys::kem::[< OQS_KEM _ $name:snake _ encaps >],
ct.as_mut_ptr(),
shk.as_mut_ptr(),
pk.as_ptr()
);
}
Ok(())
}
fn decaps(shk: &mut [u8], sk: &[u8], ct: &[u8]) -> Guaranteed<()> {
assert_eq!(shk.len(), Self::SHK_LEN);
assert_eq!(sk.len(), Self::SK_LEN);
assert_eq!(ct.len(), Self::CT_LEN);
unsafe {
oqs_call!(
::oqs_sys::kem::[< OQS_KEM _ $name:snake _ decaps >],
shk.as_mut_ptr(),
ct.as_ptr(),
sk.as_ptr()
);
}
Ok(())
}
}
}
pub use [< $name:snake >] :: [< $name:camel >];
}}
}

21
oqs/src/lib.rs Normal file
View File

@@ -0,0 +1,21 @@
macro_rules! oqs_call {
($name:path, $($args:expr),*) => {{
use oqs_sys::common::OQS_STATUS::*;
match $name($($args),*) {
OQS_SUCCESS => {}, // nop
OQS_EXTERNAL_LIB_ERROR_OPENSSL => {
panic!("OpenSSL error in liboqs' {}.", stringify!($name));
},
OQS_ERROR => {
panic!("Unknown error in liboqs' {}.", stringify!($name));
}
}
}};
($name:ident) => { oqs_call!($name, ) };
}
#[macro_use]
mod kem_macro;
oqs_kem!(kyber_512);
oqs_kem!(classic_mceliece_460896);

39
overlay.nix Normal file
View File

@@ -0,0 +1,39 @@
final: prev: {
#
### Actual rosenpass software ###
#
rosenpass = final.callPackage ./pkgs/rosenpass.nix { };
rosenpass-oci-image = final.callPackage ./pkgs/rosenpass-oci-image.nix { };
rp = final.callPackage ./pkgs/rosenpass.nix { package = "rp"; };
release-package = final.callPackage ./pkgs/release-package.nix { };
#
### Appendix ###
#
proverif-patched = prev.proverif.overrideAttrs (old: {
postInstall = ''
install -D -t $out/lib cryptoverif.pvl
'';
});
proof-proverif = final.stdenv.mkDerivation {
name = "rosenpass-proverif-proof";
version = "unstable";
src = final.lib.sources.sourceByRegex ./. [
"analyze.sh"
"marzipan(/marzipan.awk)?"
"analysis(/.*)?"
];
nativeBuildInputs = [ final.proverif final.graphviz ];
CRYPTOVERIF_LIB = final.proverif-patched + "/lib/cryptoverif.pvl";
installPhase = ''
mkdir -p $out
bash analyze.sh -color -html $out
'';
};
whitepaper = final.callPackage ./pkgs/whitepaper.nix { };
}

View File

@@ -177,7 +177,11 @@ version={4.0},
\titlehead{\centerline{\includegraphics[width=4cm]{RosenPass-Logo}}}
\title{\inserttitle}
}
\author{\csname insertauthor\endcsname}
\ifx\csname insertauthor\endcsname\relax
\author{}
\else
\author{\parbox{\linewidth}{\centering\insertauthor}}
\fi
\subject{\csname insertsubject\endcsname}
\date{\vspace{-1cm}}
}

View File

@@ -6,6 +6,7 @@ author:
- Benjamin Lipp = Max Planck Institute for Security and Privacy (MPI-SP)
- Wanja Zaeske
- Lisa Schmidt = {Scientific Illustrator \\url{mullana.de}}
- Prabhpreet Dua
abstract: |
Rosenpass is used to create post-quantum-secure VPNs. Rosenpass computes a shared key, WireGuard (WG) [@wg] uses the shared key to establish a secure connection. Rosenpass can also be used without WireGuard, deriving post-quantum-secure symmetric keys for another application. The Rosenpass protocol builds on “Post-quantum WireGuard” (PQWG) [@pqwg] and improves it by using a cookie mechanism to provide security against state disruption attacks.
@@ -218,6 +219,7 @@ The server needs to store the following variables:
* `spkm`
* `biscuit_key` Randomly chosen key used to encrypt biscuits
* `biscuit_ctr` Retransmission protection for biscuits
* `cookie_secret`- A randomized cookie secret to derive cookies sent to peer when under load. This secret changes every 120 seconds
Not mandated per se, but required in practice:
@@ -243,6 +245,7 @@ The initiator stores the following local state for each ongoing handshake:
* `ck` The chaining key
* `eski` The initiator's ephemeral secret key
* `epki` The initiator's ephemeral public key
* `cookie_value`- Cookie value sent by an initiator peer under load, used to compute cookie field in outgoing handshake to peer under load. This value expires 120 seconds from when a peer sends this value using the CookieReply message
The responder stores no state. While the responder has access to all of the above variables except for `eski`, the responder discards them after generating the RespHello message. Instead, the responder state is contained inside a cookie called a biscuit. This value is returned to the responder inside the InitConf packet. The biscuit consists of:
@@ -428,12 +431,92 @@ The responder code handling InitConf needs to deal with the biscuits and package
ICR5 and ICR6 perform biscuit replay protection using the biscuit number. This is not handled in `load_biscuit()` itself because there is the case that `biscuit_no = biscuit_used` which needs to be dealt with for retransmission handling.
### Denial of Service Mitigation and Cookies
Rosenpass derives its cookie-based DoS mitigation technique for a responder when receiving InitHello messages from Wireguard [@wg].
When the responder is under load, it may choose to not process further InitHello handshake messages, but instead to respond with a cookie reply message (see Figure \ref{img:MessageTypes}).
The sender of the exchange then uses this cookie in order to resend the message and have it accepted the following time by the reciever.
For an initiator, Rosenpass ignores all messages when under load.
#### Cookie Reply Message
The cookie reply message is sent by the responder on receiving an InitHello message when under load. It consists of the `sidi` of the initiator, a random 24-byte bitstring `nonce` and encrypting `cookie_value` into a `cookie_encrypted` reply field which consists of the following:
```pseudorust
cookie_value = lhash("cookie-value", cookie_secret, initiator_host_info)[0..16]
cookie_encrypted = XAEAD(lhash("cookie-key", spkm), nonce, cookie_value, mac_peer)
```
where `cookie_secret` is a secret variable that changes every two minutes to a random value. `initiator_host_info` is used to identify the initiator host, and is implementation-specific for the client. This paramaters used to identify the host must be carefully chosen to ensure there is a unique mapping, especially when using IPv4 and IPv6 addresses to identify the host (such as taking care of IPv6 link-local addresses). `cookie_value` is a truncated 16 byte value from the above hash operation. `mac_peer` is the `mac` field of the peer's handshake message to which message is the reply.
#### Envelope `mac` Field
Similar to `mac.1` in Wireguard handshake messages, the `mac` field of a Rosenpass envelope from a handshake packet sender's point of view consists of the following:
```pseudorust
mac = lhash("mac", spkt, MAC_WIRE_DATA)[0..16]
```
where `MAC_WIRE_DATA` represents all bytes of msg prior to `mac` field in the envelope.
If a client receives an invalid `mac` value for any message, it will discard the message.
#### Envelope cookie field
The initiator, on receiving a CookieReply message, decrypts `cookie_encrypted` and stores the `cookie_value` for the session into `peer[sid].cookie_value` for a limited time (120 seconds). This value is then used to set `cookie` field set for subsequent messages and retransmissions to the responder as follows:
```pseudorust
if (peer.cookie_value.is_none() || seconds_since_update(peer[sid].cookie_value) >= 120) {
cookie.zeroize(); //zeroed out 16 bytes bitstring
}
else {
cookie = lhash("cookie",peer.cookie_value.unwrap(),COOKIE_WIRE_DATA)
}
```
Here, `seconds_since_update(peer.cookie_value)` is the amount of time in seconds ellapsed since last cookie was received, and `COOKIE_WIRE_DATA` are the message contents of all bytes of the retransmitted message prior to the `cookie` field.
The inititator can use an invalid value for the `cookie` value, when the responder is not under load, and the responder must ignore this value.
However, when the responder is under load, it may reject InitHello messages with the invalid `cookie` value, and issue a cookie reply message.
### Conditions to trigger DoS Mechanism
This whitepaper does not mandate any specific mechanism to detect responder contention (also mentioned as the under load condition) that would trigger use of the cookie mechanism.
For the reference implemenation, Rosenpass has derived inspiration from the linux implementation of Wireguard. This implementation suggests that the reciever keep track of the number of messages it is processing at a given time.
On receiving an incoming message, if the length of the message queue to be processed exceeds a threshold `MAX_QUEUED_INCOMING_HANDSHAKES_THRESHOLD`, the client is considered under load and its state is stored as under load. In addition, the timestamp of this instant when the client was last under load is stored. When recieving subsequent messages, if the client is still in an under load state, the client will check if the time ellpased since the client was last under load has exceeded `LAST_UNDER_LOAD_WINDOW` seconds. If this is the case, the client will update its state to normal operation, and process the message in a normal fashion.
Currently, the following constants are derived from the Linux kernel implementation of Wireguard:
```pseudorust
MAX_QUEUED_INCOMING_HANDSHAKES_THRESHOLD = 4096
LAST_UNDER_LOAD_WINDOW = 1 //seconds
```
## Dealing with Packet Loss
The initiator deals with packet loss by storing the messages it sends to the responder and retransmitting them in randomized, exponentially increasing intervals until they get a response. Receiving RespHello terminates retransmission of InitHello. A Data or EmptyData message serves as acknowledgement of receiving InitConf and terminates its retransmission.
The responder does not need to do anything special to handle RespHello retransmission if the RespHello package is lost, the initiator retransmits InitHello and the responder can generate another RespHello package from that. InitConf retransmission needs to be handled specifically in the responder code because accepting an InitConf retransmission would reset the live session including the nonce counter, which would cause nonce reuse. Implementations must detect the case that `biscuit_no = biscuit_used` in ICR5, skip execution of ICR6 and ICR7, and just transmit another EmptyData package to confirm that the initiator can stop transmitting InitConf.
### Interaction with cookie reply system
The cookie reply system does not interfere with the retransmission logic discussed above.
When the initator is under load, it will ignore processing any incoming messages.
When a responder is under load and it receives an InitHello handshake message, the InitHello message will be discarded and a cookie reply message is sent. The initiator, then on the reciept of the cookie reply message, will store a decrypted `cookie_value` to set the `cookie` field to subsequently sent messages. As per the retransmission mechanism above, the initiator will send a retransmitted InitHello message with a valid `cookie` value appended. On receiving the retransmitted handshake message, the responder will validate the `cookie` value and resume with the handshake process.
When the responder is under load and it recieves an InitConf message, the message will be directly processed without checking the validity of the cookie field.
# Changelog
- Added section "Denial of Service Mitigation and Cookies", and modify "Dealing with Packet Loss" for DoS cookie mechanism
\printbibliography
\setupimage{landscape,fullpage,label=img:HandlingCode}

27
pkgs/release-package.nix Normal file
View File

@@ -0,0 +1,27 @@
{ lib, stdenvNoCC, runCommandNoCC, pkgsStatic, rosenpass, rosenpass-oci-image, rp } @ args:
let
version = rosenpass.version;
# select static packages on Linux, default packages otherwise
package =
if stdenvNoCC.hostPlatform.isLinux then
pkgsStatic.rosenpass
else args.rosenpass;
rp =
if stdenvNoCC.hostPlatform.isLinux then
pkgsStatic.rp
else args.rp;
oci-image =
if stdenvNoCC.hostPlatform.isLinux then
pkgsStatic.rosenpass-oci-image
else args.rosenpass-oci-image;
in
runCommandNoCC "lace-result" { } ''
mkdir {bin,$out}
tar -cvf $out/rosenpass-${stdenvNoCC.hostPlatform.system}-${version}.tar \
-C ${package} bin/rosenpass \
-C ${rp} bin/rp
cp ${oci-image} \
$out/rosenpass-oci-image-${stdenvNoCC.hostPlatform.system}-${version}.tar.gz
''

View File

@@ -0,0 +1,11 @@
{ dockerTools, buildEnv, rosenpass }:
dockerTools.buildImage {
name = rosenpass.name + "-oci";
copyToRoot = buildEnv {
name = "image-root";
paths = [ rosenpass ];
pathsToLink = [ "/bin" ];
};
config.Cmd = [ "/bin/rosenpass" ];
}

78
pkgs/rosenpass.nix Normal file
View File

@@ -0,0 +1,78 @@
{ lib, stdenv, rustPlatform, cmake, mandoc, removeReferencesTo, bash, package ? "rosenpass" }:
let
# whether we want to build a statically linked binary
isStatic = stdenv.targetPlatform.isStatic;
scoped = (scope: scope.result);
# source files relevant for rust
src = scoped rec {
# File suffices to include
extensions = [
"lock"
"rs"
"toml"
];
# Files to explicitly include
files = [
"to/README.md"
];
src = ../.;
filter = (path: type: scoped rec {
inherit (lib) any id removePrefix hasSuffix;
anyof = (any id);
basename = baseNameOf (toString path);
relative = removePrefix (toString src + "/") (toString path);
result = anyof [
(type == "directory")
(any (ext: hasSuffix ".${ext}" basename) extensions)
(any (file: file == relative) files)
];
});
result = lib.sources.cleanSourceWith { inherit src filter; };
};
# parsed Cargo.toml
cargoToml = builtins.fromTOML (builtins.readFile (src + "/rosenpass/Cargo.toml"));
in
rustPlatform.buildRustPackage {
name = cargoToml.package.name;
version = cargoToml.package.version;
inherit src;
cargoBuildOptions = [ "--package" package ];
cargoTestOptions = [ "--package" package ];
doCheck = true;
cargoLock = {
lockFile = src + "/Cargo.lock";
outputHashes = {
"memsec-0.6.3" = "sha256-4ri+IEqLd77cLcul3lZrmpDKj4cwuYJ8oPRAiQNGeLw=";
"uds-0.4.2" = "sha256-qlxr/iJt2AV4WryePIvqm/8/MK/iqtzegztNliR93W8=";
};
};
nativeBuildInputs = [
stdenv.cc
cmake # for oqs build in the oqs-sys crate
mandoc # for the built-in manual
removeReferencesTo
rustPlatform.bindgenHook # for C-bindings in the crypto libs
];
buildInputs = [ bash ];
hardeningDisable = lib.optional isStatic "fortify";
meta = {
inherit (cargoToml.package) description homepage;
license = with lib.licenses; [ mit asl20 ];
maintainers = [ lib.maintainers.wucke13 ];
platforms = lib.platforms.all;
};
}

29
pkgs/whitepaper.nix Normal file
View File

@@ -0,0 +1,29 @@
{ stdenvNoCC, texlive, ncurses, python3Packages, which }:
let
customTexLiveSetup = (texlive.combine {
inherit (texlive) acmart amsfonts biber biblatex biblatex-software
biblatex-trad ccicons csquotes csvsimple doclicense eso-pic fancyvrb
fontspec gitinfo2 gobble ifmtarg koma-script latexmk lm lualatex-math
markdown mathtools minted noto nunito paralist pgf scheme-basic soul
unicode-math upquote xifthen xkeyval xurl;
});
in
stdenvNoCC.mkDerivation {
name = "whitepaper";
src = ../papers;
nativeBuildInputs = [
ncurses # tput
python3Packages.pygments
customTexLiveSetup # custom tex live scheme
which
];
buildPhase = ''
export HOME=$(mktemp -d)
latexmk -r tex/CI.rc
'';
installPhase = ''
mkdir -p $out
mv *.pdf readme.md $out/
'';
}

View File

@@ -25,11 +25,11 @@ Follow [quick start instructions](https://rosenpass.eu/#start) to get a VPN up a
## Software architecture
The [rosenpass tool](./src/) is written in Rust and uses liboqs[^liboqs] and libsodium[^libsodium]. The tool establishes a symmetric key and provides it to WireGuard. Since it supplies WireGuard with key through the PSK feature using Rosenpass+WireGuard is cryptographically no less secure than using WireGuard on its own ("hybrid security"). Rosenpass refreshes the symmetric key every two minutes.
The [rosenpass tool](./src/) is written in Rust and uses liboqs[^liboqs]. The tool establishes a symmetric key and provides it to WireGuard. Since it supplies WireGuard with key through the PSK feature using Rosenpass+WireGuard is cryptographically no less secure than using WireGuard on its own ("hybrid security"). Rosenpass refreshes the symmetric key every two minutes.
As with any application a small risk of critical security issues (such as buffer overflows, remote code execution) exists; the Rosenpass application is written in the Rust programming language which is much less prone to such issues. Rosenpass can also write keys to files instead of supplying them to WireGuard With a bit of scripting the stand alone mode of the implementation can be used to run the application in a Container, VM or on another host. This mode can also be used to integrate tools other than WireGuard with Rosenpass.
The [`rp`](./rp) tool written in bash makes it easy to create a VPN using WireGuard and Rosenpass.
The [`rp`](./rp) tool written in Rust makes it easy to create a VPN using WireGuard and Rosenpass.
`rp` is easy to get started with but has a few drawbacks; it runs as root, demanding access to both WireGuard
and Rosenpass private keys, takes control of the interface and works with exactly one interface. If you do not feel confident about running Rosenpass as root, you should use the stand-alone mode to create a more secure setup using containers, jails, or virtual machines.
@@ -59,7 +59,6 @@ The code uses a variety of optimizations to speed up analysis such as using secr
A wrapper script provides instant feedback about which queries execute as expected in color: A red cross if a query fails and a green check if it succeeds.
[^liboqs]: https://openquantumsafe.org/liboqs/
[^libsodium]: https://doc.libsodium.org/
[^wg]: https://www.wireguard.com/
[^pqwg]: https://eprint.iacr.org/2020/379
[^pqwg-statedis]: Unless supplied with a pre-shared-key, but this defeats the purpose of a key exchange protocol
@@ -67,6 +66,8 @@ A wrapper script provides instant feedback about which queries execute as expect
# Getting Rosenpass
Documentation and installation guides can be found at the [Rosenpass website](https://rosenpass.eu/docs).
Rosenpass is packaged for more and more distributions, maybe also for the distribution of your choice?
[![Packaging status](https://repology.org/badge/vertical-allrepos/rosenpass.svg)](https://repology.org/project/rosenpass/versions)

88
rosenpass/Cargo.toml Normal file
View File

@@ -0,0 +1,88 @@
[package]
name = "rosenpass"
version = "0.2.1"
authors = ["Karolin Varner <karo@cupdev.net>", "wucke13 <wucke13@gmail.com>"]
edition = "2021"
license = "MIT OR Apache-2.0"
description = "Build post-quantum-secure VPNs with WireGuard!"
homepage = "https://rosenpass.eu/"
repository = "https://github.com/rosenpass/rosenpass"
readme = "readme.md"
[[bin]]
name = "rosenpass"
path = "src/main.rs"
[[bin]]
name = "rosenpass-gen-ipc-msg-types"
path = "src/bin/gen-ipc-msg-types.rs"
required-features = ["experiment_api", "internal_bin_gen_ipc_msg_types"]
[[test]]
name = "api-integration-tests"
required-features = ["experiment_api", "internal_testing"]
[[test]]
name = "api-integration-tests-api-setup"
required-features = ["experiment_api", "internal_testing"]
[[bench]]
name = "handshake"
harness = false
[dependencies]
rosenpass-util = { workspace = true }
rosenpass-constant-time = { workspace = true }
rosenpass-ciphers = { workspace = true }
rosenpass-cipher-traits = { workspace = true }
rosenpass-to = { workspace = true }
rosenpass-secret-memory = { workspace = true }
anyhow = { workspace = true }
static_assertions = { workspace = true }
memoffset = { workspace = true }
thiserror = { workspace = true }
paste = { workspace = true }
log = { workspace = true }
env_logger = { workspace = true }
serde = { workspace = true }
toml = { workspace = true }
clap = { workspace = true }
mio = { workspace = true }
rand = { workspace = true }
zerocopy = { workspace = true }
home = { workspace = true }
derive_builder = { workspace = true }
rosenpass-wireguard-broker = { workspace = true }
zeroize = { workspace = true }
hex-literal = { workspace = true, optional = true }
hex = { workspace = true, optional = true }
heck = { workspace = true, optional = true }
command-fds = { workspace = true, optional = true }
rustix = { workspace = true }
uds = { workspace = true, optional = true, features = ["mio_1xx"] }
[build-dependencies]
anyhow = { workspace = true }
[dev-dependencies]
criterion = { workspace = true }
test_bin = { workspace = true }
stacker = { workspace = true }
serial_test = { workspace = true }
procspawn = { workspace = true }
tempfile = { workspace = true }
rustix = { workspace = true }
[features]
default = ["experiment_api"]
experiment_memfd_secret = ["rosenpass-wireguard-broker/experiment_memfd_secret"]
experiment_libcrux = ["rosenpass-ciphers/experiment_libcrux"]
experiment_api = [
"hex-literal",
"uds",
"command-fds",
"rosenpass-util/experiment_file_descriptor_passing",
"rosenpass-wireguard-broker/experiment_api",
]
internal_testing = []
internal_bin_gen_ipc_msg_types = ["hex", "heck"]

View File

@@ -1,11 +1,12 @@
use anyhow::Result;
use rosenpass::{
pqkem::{EphemeralKEM, CCAKEM},
protocol::{CcaPk, CcaSk, CryptoServer, HandleMsgResult, MsgBuf, PeerPtr, SymKey},
sodium::sodium_init,
};
use rosenpass::protocol::{CryptoServer, HandleMsgResult, MsgBuf, PeerPtr, SPk, SSk, SymKey};
use std::ops::DerefMut;
use rosenpass_cipher_traits::Kem;
use rosenpass_ciphers::kem::StaticKem;
use criterion::{black_box, criterion_group, criterion_main, Criterion};
use rosenpass_secret_memory::secret_policy_try_use_memfd_secrets;
fn handle(
tx: &mut CryptoServer,
@@ -38,9 +39,9 @@ fn hs(ini: &mut CryptoServer, res: &mut CryptoServer) -> Result<()> {
Ok(())
}
fn keygen() -> Result<(CcaSk, CcaPk)> {
let (mut sk, mut pk) = (CcaSk::zero(), CcaPk::zero());
CCAKEM::keygen(sk.secret_mut(), pk.secret_mut())?;
fn keygen() -> Result<(SSk, SPk)> {
let (mut sk, mut pk) = (SSk::zero(), SPk::zero());
StaticKem::keygen(sk.secret_mut(), pk.deref_mut())?;
Ok((sk, pk))
}
@@ -57,16 +58,16 @@ fn make_server_pair() -> Result<(CryptoServer, CryptoServer)> {
}
fn criterion_benchmark(c: &mut Criterion) {
sodium_init().unwrap();
secret_policy_try_use_memfd_secrets();
let (mut a, mut b) = make_server_pair().unwrap();
c.bench_function("cca_secret_alloc", |bench| {
bench.iter(|| {
CcaSk::zero();
SSk::zero();
})
});
c.bench_function("cca_public_alloc", |bench| {
bench.iter(|| {
CcaPk::zero();
SPk::zero();
})
});
c.bench_function("keygen", |bench| {

View File

@@ -30,8 +30,7 @@ fn generate_man() -> String {
return man;
}
// TODO: Link to online manual here
"Cannot render manual page\n".into()
"Cannot render manual page. Please visit https://rosenpass.eu/docs/manuals/\n".into()
}
fn man() {

1
rosenpass/readme.md Symbolic link
View File

@@ -0,0 +1 @@
../readme.md

View File

@@ -0,0 +1,295 @@
use std::{borrow::BorrowMut, collections::VecDeque, os::fd::OwnedFd};
use anyhow::Context;
use rosenpass_to::{ops::copy_slice, To};
use rosenpass_util::{
fd::FdIo,
functional::{run, ApplyExt},
io::ReadExt,
mem::DiscardResultExt,
mio::UnixStreamExt,
result::OkExt,
};
use rosenpass_wireguard_broker::brokers::mio_client::MioBrokerClient;
use crate::{
api::{add_listen_socket_response_status, add_psk_broker_response_status},
app_server::AppServer,
protocol::BuildCryptoServer,
};
use super::{supply_keypair_response_status, Server as ApiServer};
#[derive(Debug)]
pub struct ApiHandler {
_dummy: (),
}
impl ApiHandler {
#[allow(clippy::new_without_default)]
pub fn new() -> Self {
Self { _dummy: () }
}
}
pub trait ApiHandlerContext {
fn api_handler(&self) -> &ApiHandler;
fn app_server(&self) -> &AppServer;
fn api_handler_mut(&mut self) -> &mut ApiHandler;
fn app_server_mut(&mut self) -> &mut AppServer;
}
#[derive(thiserror::Error, Debug)]
#[error("Error in SupplyKeypair")]
struct SupplyKeypairError {
status: u128,
#[source]
cause: anyhow::Error,
}
trait SupplyKeypairErrorExt<T> {
fn e_custom(self, status: u128) -> Result<T, SupplyKeypairError>;
fn einternal(self) -> Result<T, SupplyKeypairError>;
fn ealready_supplied(self) -> Result<T, SupplyKeypairError>;
fn einvalid_req(self) -> Result<T, SupplyKeypairError>;
}
impl<T, E: Into<anyhow::Error>> SupplyKeypairErrorExt<T> for Result<T, E> {
fn e_custom(self, status: u128) -> Result<T, SupplyKeypairError> {
self.map_err(|e| SupplyKeypairError {
status,
cause: e.into(),
})
}
fn einternal(self) -> Result<T, SupplyKeypairError> {
self.e_custom(supply_keypair_response_status::INTERNAL_ERROR)
}
fn ealready_supplied(self) -> Result<T, SupplyKeypairError> {
self.e_custom(supply_keypair_response_status::KEYPAIR_ALREADY_SUPPLIED)
}
fn einvalid_req(self) -> Result<T, SupplyKeypairError> {
self.e_custom(supply_keypair_response_status::INVALID_REQUEST)
}
}
impl<T> ApiServer for T
where
T: ?Sized + ApiHandlerContext,
{
fn ping(
&mut self,
req: &super::PingRequest,
_req_fds: &mut VecDeque<OwnedFd>,
res: &mut super::PingResponse,
) -> anyhow::Result<()> {
let (req, res) = (&req.payload, &mut res.payload);
copy_slice(&req.echo).to(&mut res.echo);
Ok(())
}
fn supply_keypair(
&mut self,
req: &super::SupplyKeypairRequest,
req_fds: &mut VecDeque<OwnedFd>,
res: &mut super::SupplyKeypairResponse,
) -> anyhow::Result<()> {
let outcome: Result<(), SupplyKeypairError> = run(|| {
// Acquire the file descriptors
let mut sk_io = FdIo(
req_fds
.front()
.context("First file descriptor, secret key, missing.")
.einvalid_req()?,
);
let mut pk_io = FdIo(
req_fds
.get(1)
.context("Second file descriptor, public key, missing.")
.einvalid_req()?,
);
// Actually read the secrets
let mut sk = crate::protocol::SSk::zero();
sk_io.read_exact_til_end(sk.secret_mut()).einvalid_req()?;
let mut pk = crate::protocol::SPk::zero();
pk_io.read_exact_til_end(pk.borrow_mut()).einvalid_req()?;
// Retrieve the construction site
let construction_site = self.app_server_mut().crypto_site.borrow_mut();
// Retrieve the builder
use rosenpass_util::build::ConstructionSite as C;
let maybe_builder = match construction_site {
C::Builder(builder) => Some(builder),
C::Product(_) => None,
C::Void => {
return Err(anyhow::Error::msg("CryptoServer construction side is void"))
.einternal();
}
};
// Retrieve a reference to the keypair
let Some(BuildCryptoServer {
ref mut keypair, ..
}) = maybe_builder
else {
return Err(anyhow::Error::msg("CryptoServer already built")).ealready_supplied();
};
// Supply the keypair to the CryptoServer
keypair
.insert(crate::protocol::Keypair { sk, pk })
.discard_result();
// Actually construct the CryptoServer
construction_site
.erect()
.map_err(|e| anyhow::Error::msg(format!("Error erecting the CryptoServer {e:?}")))
.einternal()?;
Ok(())
});
// Handle errors
use supply_keypair_response_status as status;
let status = match outcome {
Ok(()) => status::OK,
Err(e) => {
let lvl = match e.status {
status::INTERNAL_ERROR => log::Level::Warn,
_ => log::Level::Debug,
};
log::log!(
lvl,
"Error while processing API Request.\n Request: {:?}\n Error: {:?}",
req,
e.cause
);
if e.status == status::INTERNAL_ERROR {
return Err(e.cause);
}
e.status
}
};
res.payload.status = status;
Ok(())
}
fn add_listen_socket(
&mut self,
_req: &super::boilerplate::AddListenSocketRequest,
req_fds: &mut VecDeque<OwnedFd>,
res: &mut super::boilerplate::AddListenSocketResponse,
) -> anyhow::Result<()> {
// Retrieve file descriptor
let sock_res = run(|| -> anyhow::Result<mio::net::UdpSocket> {
let sock = req_fds
.pop_front()
.context("Invalid request socket missing.")?;
// TODO: We need to have this outside linux
#[cfg(target_os = "linux")]
rosenpass_util::fd::GetSocketProtocol::demand_udp_socket(&sock)?;
let sock = std::net::UdpSocket::from(sock);
sock.set_nonblocking(true)?;
mio::net::UdpSocket::from_std(sock).ok()
});
let sock = match sock_res {
Ok(sock) => sock,
Err(e) => {
log::debug!("Error processing AddListenSocket API request: {e:?}");
res.payload.status = add_listen_socket_response_status::INVALID_REQUEST;
return Ok(());
}
};
// Register socket
let reg_result = self.app_server_mut().register_listen_socket(sock);
if let Err(internal_error) = reg_result {
log::warn!("Internal error processing AddListenSocket API request: {internal_error:?}");
res.payload.status = add_listen_socket_response_status::INTERNAL_ERROR;
return Ok(());
};
res.payload.status = add_listen_socket_response_status::OK;
Ok(())
}
fn add_psk_broker(
&mut self,
_req: &super::boilerplate::AddPskBrokerRequest,
req_fds: &mut VecDeque<OwnedFd>,
res: &mut super::boilerplate::AddPskBrokerResponse,
) -> anyhow::Result<()> {
// Retrieve file descriptor
let sock_res = run(|| {
let sock = req_fds
.pop_front()
.context("Invalid request socket missing.")?;
mio::net::UnixStream::from_fd(sock)
});
// Handle errors
let sock = match sock_res {
Ok(sock) => sock,
Err(e) => {
log::debug!(
"Request found to be invalid while processing AddPskBroker API request: {e:?}"
);
res.payload.status = add_psk_broker_response_status::INVALID_REQUEST;
return Ok(());
}
};
// Register Socket
let client = Box::new(MioBrokerClient::new(sock));
// Workaround: The broker code is currently impressively overcomplicated. Brokers are
// stored in a hash map but the hash map key used is just a counter so a vector could
// have been used. Broker configuration is abstracted, different peers can have different
// brokers but there is no facility to add multiple brokers in practice. The broker index
// uses a `Public` wrapper without actually holding any cryptographic data. Even the broker
// configuration uses a trait abstraction for no discernible reason and a lot of the code
// introduces pointless, single-field wrapper structs.
// We should use an implement-what-is-actually-needed strategy next time.
// The Broker code needs to be slimmed down, the right direction to go is probably to
// just add event and capability support to the API and use the API to deliver OSK events.
//
// For now, we just replace the latest broker.
let erase_ptr = {
use crate::app_server::BrokerStorePtr;
//
use rosenpass_secret_memory::Public;
use zerocopy::AsBytes;
(self.app_server().brokers.store.len() - 1)
.apply(|x| x as u64)
.apply(|x| Public::from_slice(x.as_bytes()))
.apply(BrokerStorePtr)
};
let register_result = run(|| {
let srv = self.app_server_mut();
srv.unregister_broker(erase_ptr)?;
srv.register_broker(client)
});
if let Err(e) = register_result {
log::warn!("Internal error while processing AddPskBroker API request: {e:?}");
res.payload.status = add_psk_broker_response_status::INTERNAL_ERROR;
return Ok(());
}
res.payload.status = add_psk_broker_response_status::OK;
Ok(())
}
}

View File

@@ -0,0 +1,222 @@
use zerocopy::{ByteSlice, Ref};
use rosenpass_util::zerocopy::{RefMaker, ZerocopySliceExt};
use super::{
PingRequest, PingResponse, RawMsgType, RefMakerRawMsgTypeExt, RequestMsgType, RequestRef,
ResponseMsgType, ResponseRef, SupplyKeypairRequest, SupplyKeypairResponse,
};
pub trait ByteSliceRefExt: ByteSlice {
fn msg_type_maker(self) -> RefMaker<Self, RawMsgType> {
self.zk_ref_maker()
}
fn msg_type(self) -> anyhow::Result<Ref<Self, PingRequest>> {
self.zk_parse()
}
fn msg_type_from_prefix(self) -> anyhow::Result<Ref<Self, PingRequest>> {
self.zk_parse_prefix()
}
fn msg_type_from_suffix(self) -> anyhow::Result<Ref<Self, PingRequest>> {
self.zk_parse_suffix()
}
fn request_msg_type(self) -> anyhow::Result<RequestMsgType> {
self.msg_type_maker().parse_request_msg_type()
}
fn request_msg_type_from_prefix(self) -> anyhow::Result<RequestMsgType> {
self.msg_type_maker()
.from_prefix()?
.parse_request_msg_type()
}
fn request_msg_type_from_suffix(self) -> anyhow::Result<RequestMsgType> {
self.msg_type_maker()
.from_suffix()?
.parse_request_msg_type()
}
fn response_msg_type(self) -> anyhow::Result<ResponseMsgType> {
self.msg_type_maker().parse_response_msg_type()
}
fn response_msg_type_from_prefix(self) -> anyhow::Result<ResponseMsgType> {
self.msg_type_maker()
.from_prefix()?
.parse_response_msg_type()
}
fn response_msg_type_from_suffix(self) -> anyhow::Result<ResponseMsgType> {
self.msg_type_maker()
.from_suffix()?
.parse_response_msg_type()
}
fn parse_request(self) -> anyhow::Result<RequestRef<Self>> {
RequestRef::parse(self)
}
fn parse_request_from_prefix(self) -> anyhow::Result<RequestRef<Self>> {
RequestRef::parse_from_prefix(self)
}
fn parse_request_from_suffix(self) -> anyhow::Result<RequestRef<Self>> {
RequestRef::parse_from_suffix(self)
}
fn parse_response(self) -> anyhow::Result<ResponseRef<Self>> {
ResponseRef::parse(self)
}
fn parse_response_from_prefix(self) -> anyhow::Result<ResponseRef<Self>> {
ResponseRef::parse_from_prefix(self)
}
fn parse_response_from_suffix(self) -> anyhow::Result<ResponseRef<Self>> {
ResponseRef::parse_from_suffix(self)
}
fn ping_request_maker(self) -> RefMaker<Self, PingRequest> {
self.zk_ref_maker()
}
fn ping_request(self) -> anyhow::Result<Ref<Self, PingRequest>> {
self.zk_parse()
}
fn ping_request_from_prefix(self) -> anyhow::Result<Ref<Self, PingRequest>> {
self.zk_parse_prefix()
}
fn ping_request_from_suffix(self) -> anyhow::Result<Ref<Self, PingRequest>> {
self.zk_parse_suffix()
}
fn ping_response_maker(self) -> RefMaker<Self, PingResponse> {
self.zk_ref_maker()
}
fn ping_response(self) -> anyhow::Result<Ref<Self, PingResponse>> {
self.zk_parse()
}
fn ping_response_from_prefix(self) -> anyhow::Result<Ref<Self, PingResponse>> {
self.zk_parse_prefix()
}
fn ping_response_from_suffix(self) -> anyhow::Result<Ref<Self, PingResponse>> {
self.zk_parse_suffix()
}
fn supply_keypair_request(self) -> anyhow::Result<Ref<Self, SupplyKeypairRequest>> {
self.zk_parse()
}
fn supply_keypair_request_from_prefix(self) -> anyhow::Result<Ref<Self, SupplyKeypairRequest>> {
self.zk_parse_prefix()
}
fn supply_keypair_request_from_suffix(self) -> anyhow::Result<Ref<Self, SupplyKeypairRequest>> {
self.zk_parse_suffix()
}
fn supply_keypair_response_maker(self) -> RefMaker<Self, SupplyKeypairResponse> {
self.zk_ref_maker()
}
fn supply_keypair_response(self) -> anyhow::Result<Ref<Self, SupplyKeypairResponse>> {
self.zk_parse()
}
fn supply_keypair_response_from_prefix(
self,
) -> anyhow::Result<Ref<Self, SupplyKeypairResponse>> {
self.zk_parse_prefix()
}
fn supply_keypair_response_from_suffix(
self,
) -> anyhow::Result<Ref<Self, SupplyKeypairResponse>> {
self.zk_parse_suffix()
}
fn add_listen_socket_request(self) -> anyhow::Result<Ref<Self, super::AddListenSocketRequest>> {
self.zk_parse()
}
fn add_listen_socket_request_from_prefix(
self,
) -> anyhow::Result<Ref<Self, super::AddListenSocketRequest>> {
self.zk_parse_prefix()
}
fn add_listen_socket_request_from_suffix(
self,
) -> anyhow::Result<Ref<Self, super::AddListenSocketRequest>> {
self.zk_parse_suffix()
}
fn add_listen_socket_response_maker(self) -> RefMaker<Self, super::AddListenSocketResponse> {
self.zk_ref_maker()
}
fn add_listen_socket_response(
self,
) -> anyhow::Result<Ref<Self, super::AddListenSocketResponse>> {
self.zk_parse()
}
fn add_listen_socket_response_from_prefix(
self,
) -> anyhow::Result<Ref<Self, super::AddListenSocketResponse>> {
self.zk_parse_prefix()
}
fn add_listen_socket_response_from_suffix(
self,
) -> anyhow::Result<Ref<Self, super::AddListenSocketResponse>> {
self.zk_parse_suffix()
}
fn add_psk_broker_request(self) -> anyhow::Result<Ref<Self, super::AddPskBrokerRequest>> {
self.zk_parse()
}
fn add_psk_broker_request_from_prefix(
self,
) -> anyhow::Result<Ref<Self, super::AddPskBrokerRequest>> {
self.zk_parse_prefix()
}
fn add_psk_broker_request_from_suffix(
self,
) -> anyhow::Result<Ref<Self, super::AddPskBrokerRequest>> {
self.zk_parse_suffix()
}
fn add_psk_broker_response_maker(self) -> RefMaker<Self, super::AddPskBrokerResponse> {
self.zk_ref_maker()
}
fn add_psk_broker_response(self) -> anyhow::Result<Ref<Self, super::AddPskBrokerResponse>> {
self.zk_parse()
}
fn add_psk_broker_response_from_prefix(
self,
) -> anyhow::Result<Ref<Self, super::AddPskBrokerResponse>> {
self.zk_parse_prefix()
}
fn add_psk_broker_response_from_suffix(
self,
) -> anyhow::Result<Ref<Self, super::AddPskBrokerResponse>> {
self.zk_parse_suffix()
}
}
impl<B: ByteSlice> ByteSliceRefExt for B {}

View File

@@ -0,0 +1,29 @@
use zerocopy::{ByteSliceMut, Ref};
use rosenpass_util::zerocopy::RefMaker;
use super::RawMsgType;
pub trait Message {
type Payload;
type MessageClass: Into<RawMsgType>;
const MESSAGE_TYPE: Self::MessageClass;
fn from_payload(payload: Self::Payload) -> Self;
fn init(&mut self);
fn setup<B: ByteSliceMut>(buf: B) -> anyhow::Result<Ref<B, Self>>;
}
pub trait ZerocopyResponseMakerSetupMessageExt<B, T> {
fn setup_msg(self) -> anyhow::Result<Ref<B, T>>;
}
impl<B, T> ZerocopyResponseMakerSetupMessageExt<B, T> for RefMaker<B, T>
where
B: ByteSliceMut,
T: Message,
{
fn setup_msg(self) -> anyhow::Result<Ref<B, T>> {
T::setup(self.into_buf())
}
}

View File

@@ -0,0 +1,162 @@
use hex_literal::hex;
use rosenpass_util::zerocopy::RefMaker;
use zerocopy::ByteSlice;
use crate::RosenpassError::{self, InvalidApiMessageType};
pub type RawMsgType = u128;
// constants generated by gen-ipc-msg-types:
// hash domain hash of: Rosenpass IPC API -> Rosenpass Protocol Server -> Ping Request
pub const PING_REQUEST: RawMsgType =
RawMsgType::from_le_bytes(hex!("2397 3ecc c441 704d 0b02 ea31 45d3 4999"));
// hash domain hash of: Rosenpass IPC API -> Rosenpass Protocol Server -> Ping Response
pub const PING_RESPONSE: RawMsgType =
RawMsgType::from_le_bytes(hex!("4ec7 f6f0 2bbc ba64 48f1 da14 c7cf 0260"));
// hash domain hash of: Rosenpass IPC API -> Rosenpass Protocol Server -> Supply Keypair Request
const SUPPLY_KEYPAIR_REQUEST: RawMsgType =
RawMsgType::from_le_bytes(hex!("ac91 a5a6 4f4b 21d0 ac7f 9b55 74f7 3529"));
// hash domain hash of: Rosenpass IPC API -> Rosenpass Protocol Server -> Supply Keypair Response
const SUPPLY_KEYPAIR_RESPONSE: RawMsgType =
RawMsgType::from_le_bytes(hex!("f2dc 49bd e261 5f10 40b7 3c16 ec61 edb9"));
// hash domain hash of: Rosenpass IPC API -> Rosenpass Protocol Server -> Add Listen Socket Request
const ADD_LISTEN_SOCKET_REQUEST: RawMsgType =
RawMsgType::from_le_bytes(hex!("3f21 434f 87cc a08c 02c4 61e4 0816 c7da"));
// hash domain hash of: Rosenpass IPC API -> Rosenpass Protocol Server -> Add Listen Socket Response
const ADD_LISTEN_SOCKET_RESPONSE: RawMsgType =
RawMsgType::from_le_bytes(hex!("45d5 0f0d 93f0 6105 98f2 9469 5dfd 5f36"));
// hash domain hash of: Rosenpass IPC API -> Rosenpass Protocol Server -> Add Psk Broker Request
const ADD_PSK_BROKER_REQUEST: RawMsgType =
RawMsgType::from_le_bytes(hex!("d798 b8dc bd61 5cab 8df1 c63d e4eb a2d1"));
// hash domain hash of: Rosenpass IPC API -> Rosenpass Protocol Server -> Add Psk Broker Response
const ADD_PSK_BROKER_RESPONSE: RawMsgType =
RawMsgType::from_le_bytes(hex!("bd25 e418 ffb0 6930 248b 217e 2fae e353"));
pub trait MessageAttributes {
fn message_size(&self) -> usize;
}
#[derive(Hash, PartialEq, Eq, PartialOrd, Ord, Debug, Clone, Copy)]
pub enum RequestMsgType {
Ping,
SupplyKeypair,
AddListenSocket,
AddPskBroker,
}
#[derive(Hash, PartialEq, Eq, PartialOrd, Ord, Debug, Clone, Copy)]
pub enum ResponseMsgType {
Ping,
SupplyKeypair,
AddListenSocket,
AddPskBroker,
}
impl MessageAttributes for RequestMsgType {
fn message_size(&self) -> usize {
match self {
Self::Ping => std::mem::size_of::<super::PingRequest>(),
Self::SupplyKeypair => std::mem::size_of::<super::SupplyKeypairRequest>(),
Self::AddListenSocket => std::mem::size_of::<super::AddListenSocketRequest>(),
Self::AddPskBroker => std::mem::size_of::<super::AddPskBrokerRequest>(),
}
}
}
impl MessageAttributes for ResponseMsgType {
fn message_size(&self) -> usize {
match self {
Self::Ping => std::mem::size_of::<super::PingResponse>(),
Self::SupplyKeypair => std::mem::size_of::<super::SupplyKeypairResponse>(),
Self::AddListenSocket => std::mem::size_of::<super::AddListenSocketResponse>(),
Self::AddPskBroker => std::mem::size_of::<super::AddPskBrokerResponse>(),
}
}
}
impl TryFrom<RawMsgType> for RequestMsgType {
type Error = RosenpassError;
fn try_from(value: RawMsgType) -> Result<Self, Self::Error> {
use RequestMsgType as E;
Ok(match value {
self::PING_REQUEST => E::Ping,
self::SUPPLY_KEYPAIR_REQUEST => E::SupplyKeypair,
self::ADD_LISTEN_SOCKET_REQUEST => E::AddListenSocket,
self::ADD_PSK_BROKER_REQUEST => E::AddPskBroker,
_ => return Err(InvalidApiMessageType(value)),
})
}
}
impl From<RequestMsgType> for RawMsgType {
fn from(val: RequestMsgType) -> Self {
use RequestMsgType as E;
match val {
E::Ping => self::PING_REQUEST,
E::SupplyKeypair => self::SUPPLY_KEYPAIR_REQUEST,
E::AddListenSocket => self::ADD_LISTEN_SOCKET_REQUEST,
E::AddPskBroker => self::ADD_PSK_BROKER_REQUEST,
}
}
}
impl TryFrom<RawMsgType> for ResponseMsgType {
type Error = RosenpassError;
fn try_from(value: RawMsgType) -> Result<Self, Self::Error> {
use ResponseMsgType as E;
Ok(match value {
self::PING_RESPONSE => E::Ping,
self::SUPPLY_KEYPAIR_RESPONSE => E::SupplyKeypair,
self::ADD_LISTEN_SOCKET_RESPONSE => E::AddListenSocket,
self::ADD_PSK_BROKER_RESPONSE => E::AddPskBroker,
_ => return Err(InvalidApiMessageType(value)),
})
}
}
impl From<ResponseMsgType> for RawMsgType {
fn from(val: ResponseMsgType) -> Self {
use ResponseMsgType as E;
match val {
E::Ping => self::PING_RESPONSE,
E::SupplyKeypair => self::SUPPLY_KEYPAIR_RESPONSE,
E::AddListenSocket => self::ADD_LISTEN_SOCKET_RESPONSE,
E::AddPskBroker => self::ADD_PSK_BROKER_RESPONSE,
}
}
}
pub trait RawMsgTypeExt {
fn into_request_msg_type(self) -> Result<RequestMsgType, RosenpassError>;
fn into_response_msg_type(self) -> Result<ResponseMsgType, RosenpassError>;
}
impl RawMsgTypeExt for RawMsgType {
fn into_request_msg_type(self) -> Result<RequestMsgType, RosenpassError> {
self.try_into()
}
fn into_response_msg_type(self) -> Result<ResponseMsgType, RosenpassError> {
self.try_into()
}
}
pub trait RefMakerRawMsgTypeExt {
fn parse_request_msg_type(self) -> anyhow::Result<RequestMsgType>;
fn parse_response_msg_type(self) -> anyhow::Result<ResponseMsgType>;
}
impl<B: ByteSlice> RefMakerRawMsgTypeExt for RefMaker<B, RawMsgType> {
fn parse_request_msg_type(self) -> anyhow::Result<RequestMsgType> {
Ok(self.parse()?.read().try_into()?)
}
fn parse_response_msg_type(self) -> anyhow::Result<ResponseMsgType> {
Ok(self.parse()?.read().try_into()?)
}
}

View File

@@ -0,0 +1,17 @@
mod byte_slice_ext;
mod message_trait;
mod message_type;
mod payload;
mod request_ref;
mod request_response;
mod response_ref;
mod server;
pub use byte_slice_ext::*;
pub use message_trait::*;
pub use message_type::*;
pub use payload::*;
pub use request_ref::*;
pub use request_response::*;
pub use response_ref::*;
pub use server::*;

View File

@@ -0,0 +1,351 @@
use rosenpass_util::zerocopy::ZerocopyMutSliceExt;
use zerocopy::{AsBytes, ByteSliceMut, FromBytes, FromZeroes, Ref};
use super::{Message, RawMsgType, RequestMsgType, ResponseMsgType};
/// Size required to fit any message in binary form
pub const MAX_REQUEST_LEN: usize = 2500; // TODO fix this
pub const MAX_RESPONSE_LEN: usize = 2500; // TODO fix this
pub const MAX_REQUEST_FDS: usize = 2;
#[repr(packed)]
#[derive(Debug, Copy, Clone, Hash, AsBytes, FromBytes, FromZeroes, PartialEq, Eq)]
pub struct Envelope<M: AsBytes + FromBytes> {
/// Which message this is
pub msg_type: RawMsgType,
/// The actual Paylod
pub payload: M,
}
pub type RequestEnvelope<M> = Envelope<M>;
pub type ResponseEnvelope<M> = Envelope<M>;
#[repr(packed)]
#[derive(Debug, Copy, Clone, Hash, AsBytes, FromBytes, FromZeroes, PartialEq, Eq)]
pub struct PingRequestPayload {
/// Randomly generated connection id
pub echo: [u8; 256],
}
pub type PingRequest = RequestEnvelope<PingRequestPayload>;
impl PingRequest {
pub fn new(echo: [u8; 256]) -> Self {
Self::from_payload(PingRequestPayload { echo })
}
}
impl Message for PingRequest {
type Payload = PingRequestPayload;
type MessageClass = RequestMsgType;
const MESSAGE_TYPE: Self::MessageClass = RequestMsgType::Ping;
fn from_payload(payload: Self::Payload) -> Self {
Self {
msg_type: Self::MESSAGE_TYPE.into(),
payload,
}
}
fn setup<B: ByteSliceMut>(buf: B) -> anyhow::Result<Ref<B, Self>> {
let mut r: Ref<B, Self> = buf.zk_zeroized()?;
r.init();
Ok(r)
}
fn init(&mut self) {
self.msg_type = Self::MESSAGE_TYPE.into();
}
}
#[repr(packed)]
#[derive(Debug, Copy, Clone, Hash, AsBytes, FromBytes, FromZeroes, PartialEq, Eq)]
pub struct PingResponsePayload {
/// Randomly generated connection id
pub echo: [u8; 256],
}
pub type PingResponse = ResponseEnvelope<PingResponsePayload>;
impl PingResponse {
pub fn new(echo: [u8; 256]) -> Self {
Self::from_payload(PingResponsePayload { echo })
}
}
impl Message for PingResponse {
type Payload = PingResponsePayload;
type MessageClass = ResponseMsgType;
const MESSAGE_TYPE: Self::MessageClass = ResponseMsgType::Ping;
fn from_payload(payload: Self::Payload) -> Self {
Self {
msg_type: Self::MESSAGE_TYPE.into(),
payload,
}
}
fn setup<B: ByteSliceMut>(buf: B) -> anyhow::Result<Ref<B, Self>> {
let mut r: Ref<B, Self> = buf.zk_zeroized()?;
r.init();
Ok(r)
}
fn init(&mut self) {
self.msg_type = Self::MESSAGE_TYPE.into();
}
}
#[repr(packed)]
#[derive(Debug, Copy, Clone, Hash, AsBytes, FromBytes, FromZeroes, PartialEq, Eq)]
pub struct SupplyKeypairRequestPayload {}
pub type SupplyKeypairRequest = RequestEnvelope<SupplyKeypairRequestPayload>;
impl Default for SupplyKeypairRequest {
fn default() -> Self {
Self::new()
}
}
impl SupplyKeypairRequest {
pub fn new() -> Self {
Self::from_payload(SupplyKeypairRequestPayload {})
}
}
impl Message for SupplyKeypairRequest {
type Payload = SupplyKeypairRequestPayload;
type MessageClass = RequestMsgType;
const MESSAGE_TYPE: Self::MessageClass = RequestMsgType::SupplyKeypair;
fn from_payload(payload: Self::Payload) -> Self {
Self {
msg_type: Self::MESSAGE_TYPE.into(),
payload,
}
}
fn setup<B: ByteSliceMut>(buf: B) -> anyhow::Result<Ref<B, Self>> {
let mut r: Ref<B, Self> = buf.zk_zeroized()?;
r.init();
Ok(r)
}
fn init(&mut self) {
self.msg_type = Self::MESSAGE_TYPE.into();
}
}
pub mod supply_keypair_response_status {
pub const OK: u128 = 0;
pub const KEYPAIR_ALREADY_SUPPLIED: u128 = 1;
pub const INTERNAL_ERROR: u128 = 2;
pub const INVALID_REQUEST: u128 = 3;
pub const IO_ERROR: u128 = 4;
}
#[repr(packed)]
#[derive(Debug, Copy, Clone, Hash, AsBytes, FromBytes, FromZeroes, PartialEq, Eq)]
pub struct SupplyKeypairResponsePayload {
pub status: u128,
}
pub type SupplyKeypairResponse = ResponseEnvelope<SupplyKeypairResponsePayload>;
impl SupplyKeypairResponse {
pub fn new(status: u128) -> Self {
Self::from_payload(SupplyKeypairResponsePayload { status })
}
}
impl Message for SupplyKeypairResponse {
type Payload = SupplyKeypairResponsePayload;
type MessageClass = ResponseMsgType;
const MESSAGE_TYPE: Self::MessageClass = ResponseMsgType::SupplyKeypair;
fn from_payload(payload: Self::Payload) -> Self {
Self {
msg_type: Self::MESSAGE_TYPE.into(),
payload,
}
}
fn setup<B: ByteSliceMut>(buf: B) -> anyhow::Result<Ref<B, Self>> {
let mut r: Ref<B, Self> = buf.zk_zeroized()?;
r.init();
Ok(r)
}
fn init(&mut self) {
self.msg_type = Self::MESSAGE_TYPE.into();
}
}
#[repr(packed)]
#[derive(Debug, Copy, Clone, Hash, AsBytes, FromBytes, FromZeroes, PartialEq, Eq)]
pub struct AddListenSocketRequestPayload {}
pub type AddListenSocketRequest = RequestEnvelope<AddListenSocketRequestPayload>;
impl Default for AddListenSocketRequest {
fn default() -> Self {
Self::new()
}
}
impl AddListenSocketRequest {
pub fn new() -> Self {
Self::from_payload(AddListenSocketRequestPayload {})
}
}
impl Message for AddListenSocketRequest {
type Payload = AddListenSocketRequestPayload;
type MessageClass = RequestMsgType;
const MESSAGE_TYPE: Self::MessageClass = RequestMsgType::AddListenSocket;
fn from_payload(payload: Self::Payload) -> Self {
Self {
msg_type: Self::MESSAGE_TYPE.into(),
payload,
}
}
fn setup<B: ByteSliceMut>(buf: B) -> anyhow::Result<Ref<B, Self>> {
let mut r: Ref<B, Self> = buf.zk_zeroized()?;
r.init();
Ok(r)
}
fn init(&mut self) {
self.msg_type = Self::MESSAGE_TYPE.into();
}
}
pub mod add_listen_socket_response_status {
pub const OK: u128 = 0;
pub const INVALID_REQUEST: u128 = 1;
pub const INTERNAL_ERROR: u128 = 2;
}
#[repr(packed)]
#[derive(Debug, Copy, Clone, Hash, AsBytes, FromBytes, FromZeroes, PartialEq, Eq)]
pub struct AddListenSocketResponsePayload {
pub status: u128,
}
pub type AddListenSocketResponse = ResponseEnvelope<AddListenSocketResponsePayload>;
impl AddListenSocketResponse {
pub fn new(status: u128) -> Self {
Self::from_payload(AddListenSocketResponsePayload { status })
}
}
impl Message for AddListenSocketResponse {
type Payload = AddListenSocketResponsePayload;
type MessageClass = ResponseMsgType;
const MESSAGE_TYPE: Self::MessageClass = ResponseMsgType::AddListenSocket;
fn from_payload(payload: Self::Payload) -> Self {
Self {
msg_type: Self::MESSAGE_TYPE.into(),
payload,
}
}
fn setup<B: ByteSliceMut>(buf: B) -> anyhow::Result<Ref<B, Self>> {
let mut r: Ref<B, Self> = buf.zk_zeroized()?;
r.init();
Ok(r)
}
fn init(&mut self) {
self.msg_type = Self::MESSAGE_TYPE.into();
}
}
#[repr(packed)]
#[derive(Debug, Copy, Clone, Hash, AsBytes, FromBytes, FromZeroes, PartialEq, Eq)]
pub struct AddPskBrokerRequestPayload {}
pub type AddPskBrokerRequest = RequestEnvelope<AddPskBrokerRequestPayload>;
impl Default for AddPskBrokerRequest {
fn default() -> Self {
Self::new()
}
}
impl AddPskBrokerRequest {
pub fn new() -> Self {
Self::from_payload(AddPskBrokerRequestPayload {})
}
}
impl Message for AddPskBrokerRequest {
type Payload = AddPskBrokerRequestPayload;
type MessageClass = RequestMsgType;
const MESSAGE_TYPE: Self::MessageClass = RequestMsgType::AddPskBroker;
fn from_payload(payload: Self::Payload) -> Self {
Self {
msg_type: Self::MESSAGE_TYPE.into(),
payload,
}
}
fn setup<B: ByteSliceMut>(buf: B) -> anyhow::Result<Ref<B, Self>> {
let mut r: Ref<B, Self> = buf.zk_zeroized()?;
r.init();
Ok(r)
}
fn init(&mut self) {
self.msg_type = Self::MESSAGE_TYPE.into();
}
}
pub mod add_psk_broker_response_status {
pub const OK: u128 = 0;
pub const INVALID_REQUEST: u128 = 1;
pub const INTERNAL_ERROR: u128 = 2;
}
#[repr(packed)]
#[derive(Debug, Copy, Clone, Hash, AsBytes, FromBytes, FromZeroes, PartialEq, Eq)]
pub struct AddPskBrokerResponsePayload {
pub status: u128,
}
pub type AddPskBrokerResponse = ResponseEnvelope<AddPskBrokerResponsePayload>;
impl AddPskBrokerResponse {
pub fn new(status: u128) -> Self {
Self::from_payload(AddPskBrokerResponsePayload { status })
}
}
impl Message for AddPskBrokerResponse {
type Payload = AddPskBrokerResponsePayload;
type MessageClass = ResponseMsgType;
const MESSAGE_TYPE: Self::MessageClass = ResponseMsgType::AddPskBroker;
fn from_payload(payload: Self::Payload) -> Self {
Self {
msg_type: Self::MESSAGE_TYPE.into(),
payload,
}
}
fn setup<B: ByteSliceMut>(buf: B) -> anyhow::Result<Ref<B, Self>> {
let mut r: Ref<B, Self> = buf.zk_zeroized()?;
r.init();
Ok(r)
}
fn init(&mut self) {
self.msg_type = Self::MESSAGE_TYPE.into();
}
}

View File

@@ -0,0 +1,146 @@
use anyhow::ensure;
use zerocopy::{ByteSlice, ByteSliceMut, Ref};
use super::{ByteSliceRefExt, MessageAttributes, PingRequest, RequestMsgType};
struct RequestRefMaker<B> {
buf: B,
msg_type: RequestMsgType,
}
impl<B: ByteSlice> RequestRef<B> {
pub fn parse(buf: B) -> anyhow::Result<Self> {
RequestRefMaker::new(buf)?.parse()
}
pub fn parse_from_prefix(buf: B) -> anyhow::Result<Self> {
RequestRefMaker::new(buf)?.from_prefix()?.parse()
}
pub fn parse_from_suffix(buf: B) -> anyhow::Result<Self> {
RequestRefMaker::new(buf)?.from_suffix()?.parse()
}
pub fn message_type(&self) -> RequestMsgType {
match self {
Self::Ping(_) => RequestMsgType::Ping,
Self::SupplyKeypair(_) => RequestMsgType::SupplyKeypair,
Self::AddListenSocket(_) => RequestMsgType::AddListenSocket,
Self::AddPskBroker(_) => RequestMsgType::AddPskBroker,
}
}
}
impl<B> From<Ref<B, PingRequest>> for RequestRef<B> {
fn from(v: Ref<B, PingRequest>) -> Self {
Self::Ping(v)
}
}
impl<B> From<Ref<B, super::SupplyKeypairRequest>> for RequestRef<B> {
fn from(v: Ref<B, super::SupplyKeypairRequest>) -> Self {
Self::SupplyKeypair(v)
}
}
impl<B> From<Ref<B, super::AddListenSocketRequest>> for RequestRef<B> {
fn from(v: Ref<B, super::AddListenSocketRequest>) -> Self {
Self::AddListenSocket(v)
}
}
impl<B> From<Ref<B, super::AddPskBrokerRequest>> for RequestRef<B> {
fn from(v: Ref<B, super::AddPskBrokerRequest>) -> Self {
Self::AddPskBroker(v)
}
}
impl<B: ByteSlice> RequestRefMaker<B> {
fn new(buf: B) -> anyhow::Result<Self> {
let msg_type = buf.deref().request_msg_type_from_prefix()?;
Ok(Self { buf, msg_type })
}
fn target_size(&self) -> usize {
self.msg_type.message_size()
}
fn parse(self) -> anyhow::Result<RequestRef<B>> {
Ok(match self.msg_type {
RequestMsgType::Ping => RequestRef::Ping(self.buf.ping_request()?),
RequestMsgType::SupplyKeypair => {
RequestRef::SupplyKeypair(self.buf.supply_keypair_request()?)
}
RequestMsgType::AddListenSocket => {
RequestRef::AddListenSocket(self.buf.add_listen_socket_request()?)
}
RequestMsgType::AddPskBroker => {
RequestRef::AddPskBroker(self.buf.add_psk_broker_request()?)
}
})
}
#[allow(clippy::wrong_self_convention)]
fn from_prefix(self) -> anyhow::Result<Self> {
self.ensure_fit()?;
let point = self.target_size();
let Self { buf, msg_type } = self;
let (buf, _) = buf.split_at(point);
Ok(Self { buf, msg_type })
}
#[allow(clippy::wrong_self_convention)]
fn from_suffix(self) -> anyhow::Result<Self> {
self.ensure_fit()?;
let point = self.buf.len() - self.target_size();
let Self { buf, msg_type } = self;
let (buf, _) = buf.split_at(point);
Ok(Self { buf, msg_type })
}
pub fn ensure_fit(&self) -> anyhow::Result<()> {
let have = self.buf.len();
let need = self.target_size();
ensure!(
need <= have,
"Buffer is undersized at {have} bytes (need {need} bytes)!"
);
Ok(())
}
}
pub enum RequestRef<B> {
Ping(Ref<B, PingRequest>),
SupplyKeypair(Ref<B, super::SupplyKeypairRequest>),
AddListenSocket(Ref<B, super::AddListenSocketRequest>),
AddPskBroker(Ref<B, super::AddPskBrokerRequest>),
}
impl<B> RequestRef<B>
where
B: ByteSlice,
{
pub fn bytes(&self) -> &[u8] {
match self {
Self::Ping(r) => r.bytes(),
Self::SupplyKeypair(r) => r.bytes(),
Self::AddListenSocket(r) => r.bytes(),
Self::AddPskBroker(r) => r.bytes(),
}
}
}
impl<B> RequestRef<B>
where
B: ByteSliceMut,
{
pub fn bytes_mut(&mut self) -> &[u8] {
match self {
Self::Ping(r) => r.bytes_mut(),
Self::SupplyKeypair(r) => r.bytes_mut(),
Self::AddListenSocket(r) => r.bytes_mut(),
Self::AddPskBroker(r) => r.bytes_mut(),
}
}
}

View File

@@ -0,0 +1,190 @@
use rosenpass_util::zerocopy::{
RefMaker, ZerocopyEmancipateExt, ZerocopyEmancipateMutExt, ZerocopySliceExt,
};
use zerocopy::{ByteSlice, ByteSliceMut, Ref};
use super::{Message, PingRequest, PingResponse};
use super::{RequestRef, ResponseRef, ZerocopyResponseMakerSetupMessageExt};
pub trait RequestMsg: Sized + Message {
type ResponseMsg: ResponseMsg;
fn zk_response_maker<B: ByteSlice>(buf: B) -> RefMaker<B, Self::ResponseMsg> {
buf.zk_ref_maker()
}
fn setup_response<B: ByteSliceMut>(buf: B) -> anyhow::Result<Ref<B, Self::ResponseMsg>> {
Self::zk_response_maker(buf).setup_msg()
}
fn setup_response_from_prefix<B: ByteSliceMut>(
buf: B,
) -> anyhow::Result<Ref<B, Self::ResponseMsg>> {
Self::zk_response_maker(buf).from_prefix()?.setup_msg()
}
fn setup_response_from_suffix<B: ByteSliceMut>(
buf: B,
) -> anyhow::Result<Ref<B, Self::ResponseMsg>> {
Self::zk_response_maker(buf).from_prefix()?.setup_msg()
}
}
pub trait ResponseMsg: Message {
type RequestMsg: RequestMsg;
}
impl RequestMsg for PingRequest {
type ResponseMsg = PingResponse;
}
impl ResponseMsg for PingResponse {
type RequestMsg = PingRequest;
}
impl RequestMsg for super::SupplyKeypairRequest {
type ResponseMsg = super::SupplyKeypairResponse;
}
impl ResponseMsg for super::SupplyKeypairResponse {
type RequestMsg = super::SupplyKeypairRequest;
}
impl RequestMsg for super::AddListenSocketRequest {
type ResponseMsg = super::AddListenSocketResponse;
}
impl ResponseMsg for super::AddListenSocketResponse {
type RequestMsg = super::AddListenSocketRequest;
}
impl RequestMsg for super::AddPskBrokerRequest {
type ResponseMsg = super::AddPskBrokerResponse;
}
impl ResponseMsg for super::AddPskBrokerResponse {
type RequestMsg = super::AddPskBrokerRequest;
}
pub type PingPair<B1, B2> = (Ref<B1, PingRequest>, Ref<B2, PingResponse>);
pub type SupplyKeypairPair<B1, B2> = (
Ref<B1, super::SupplyKeypairRequest>,
Ref<B2, super::SupplyKeypairResponse>,
);
pub type AddListenSocketPair<B1, B2> = (
Ref<B1, super::AddListenSocketRequest>,
Ref<B2, super::AddListenSocketResponse>,
);
pub type AddPskBrokerPair<B1, B2> = (
Ref<B1, super::AddPskBrokerRequest>,
Ref<B2, super::AddPskBrokerResponse>,
);
pub enum RequestResponsePair<B1, B2> {
Ping(PingPair<B1, B2>),
SupplyKeypair(SupplyKeypairPair<B1, B2>),
AddListenSocket(AddListenSocketPair<B1, B2>),
AddPskBroker(AddPskBrokerPair<B1, B2>),
}
impl<B1, B2> From<PingPair<B1, B2>> for RequestResponsePair<B1, B2> {
fn from(v: PingPair<B1, B2>) -> Self {
RequestResponsePair::Ping(v)
}
}
impl<B1, B2> From<SupplyKeypairPair<B1, B2>> for RequestResponsePair<B1, B2> {
fn from(v: SupplyKeypairPair<B1, B2>) -> Self {
RequestResponsePair::SupplyKeypair(v)
}
}
impl<B1, B2> From<AddListenSocketPair<B1, B2>> for RequestResponsePair<B1, B2> {
fn from(v: AddListenSocketPair<B1, B2>) -> Self {
RequestResponsePair::AddListenSocket(v)
}
}
impl<B1, B2> From<AddPskBrokerPair<B1, B2>> for RequestResponsePair<B1, B2> {
fn from(v: AddPskBrokerPair<B1, B2>) -> Self {
RequestResponsePair::AddPskBroker(v)
}
}
impl<B1, B2> RequestResponsePair<B1, B2>
where
B1: ByteSlice,
B2: ByteSlice,
{
pub fn both(&self) -> (RequestRef<&[u8]>, ResponseRef<&[u8]>) {
match self {
Self::Ping((req, res)) => {
let req = RequestRef::Ping(req.emancipate());
let res = ResponseRef::Ping(res.emancipate());
(req, res)
}
Self::SupplyKeypair((req, res)) => {
let req = RequestRef::SupplyKeypair(req.emancipate());
let res = ResponseRef::SupplyKeypair(res.emancipate());
(req, res)
}
Self::AddListenSocket((req, res)) => {
let req = RequestRef::AddListenSocket(req.emancipate());
let res = ResponseRef::AddListenSocket(res.emancipate());
(req, res)
}
Self::AddPskBroker((req, res)) => {
let req = RequestRef::AddPskBroker(req.emancipate());
let res = ResponseRef::AddPskBroker(res.emancipate());
(req, res)
}
}
}
pub fn request(&self) -> RequestRef<&[u8]> {
self.both().0
}
pub fn response(&self) -> ResponseRef<&[u8]> {
self.both().1
}
}
impl<B1, B2> RequestResponsePair<B1, B2>
where
B1: ByteSliceMut,
B2: ByteSliceMut,
{
pub fn both_mut(&mut self) -> (RequestRef<&mut [u8]>, ResponseRef<&mut [u8]>) {
match self {
Self::Ping((req, res)) => {
let req = RequestRef::Ping(req.emancipate_mut());
let res = ResponseRef::Ping(res.emancipate_mut());
(req, res)
}
Self::SupplyKeypair((req, res)) => {
let req = RequestRef::SupplyKeypair(req.emancipate_mut());
let res = ResponseRef::SupplyKeypair(res.emancipate_mut());
(req, res)
}
Self::AddListenSocket((req, res)) => {
let req = RequestRef::AddListenSocket(req.emancipate_mut());
let res = ResponseRef::AddListenSocket(res.emancipate_mut());
(req, res)
}
Self::AddPskBroker((req, res)) => {
let req = RequestRef::AddPskBroker(req.emancipate_mut());
let res = ResponseRef::AddPskBroker(res.emancipate_mut());
(req, res)
}
}
}
pub fn request_mut(&mut self) -> RequestRef<&mut [u8]> {
self.both_mut().0
}
pub fn response_mut(&mut self) -> ResponseRef<&mut [u8]> {
self.both_mut().1
}
}

View File

@@ -0,0 +1,147 @@
// TODO: This is copied verbatim from ResponseRef…not pretty
use anyhow::ensure;
use zerocopy::{ByteSlice, ByteSliceMut, Ref};
use super::{ByteSliceRefExt, MessageAttributes, PingResponse, ResponseMsgType};
struct ResponseRefMaker<B> {
buf: B,
msg_type: ResponseMsgType,
}
impl<B: ByteSlice> ResponseRef<B> {
pub fn parse(buf: B) -> anyhow::Result<Self> {
ResponseRefMaker::new(buf)?.parse()
}
pub fn parse_from_prefix(buf: B) -> anyhow::Result<Self> {
ResponseRefMaker::new(buf)?.from_prefix()?.parse()
}
pub fn parse_from_suffix(buf: B) -> anyhow::Result<Self> {
ResponseRefMaker::new(buf)?.from_suffix()?.parse()
}
pub fn message_type(&self) -> ResponseMsgType {
match self {
Self::Ping(_) => ResponseMsgType::Ping,
Self::SupplyKeypair(_) => ResponseMsgType::SupplyKeypair,
Self::AddListenSocket(_) => ResponseMsgType::AddListenSocket,
Self::AddPskBroker(_) => ResponseMsgType::AddPskBroker,
}
}
}
impl<B> From<Ref<B, PingResponse>> for ResponseRef<B> {
fn from(v: Ref<B, PingResponse>) -> Self {
Self::Ping(v)
}
}
impl<B> From<Ref<B, super::SupplyKeypairResponse>> for ResponseRef<B> {
fn from(v: Ref<B, super::SupplyKeypairResponse>) -> Self {
Self::SupplyKeypair(v)
}
}
impl<B> From<Ref<B, super::AddListenSocketResponse>> for ResponseRef<B> {
fn from(v: Ref<B, super::AddListenSocketResponse>) -> Self {
Self::AddListenSocket(v)
}
}
impl<B> From<Ref<B, super::AddPskBrokerResponse>> for ResponseRef<B> {
fn from(v: Ref<B, super::AddPskBrokerResponse>) -> Self {
Self::AddPskBroker(v)
}
}
impl<B: ByteSlice> ResponseRefMaker<B> {
fn new(buf: B) -> anyhow::Result<Self> {
let msg_type = buf.deref().response_msg_type_from_prefix()?;
Ok(Self { buf, msg_type })
}
fn target_size(&self) -> usize {
self.msg_type.message_size()
}
fn parse(self) -> anyhow::Result<ResponseRef<B>> {
Ok(match self.msg_type {
ResponseMsgType::Ping => ResponseRef::Ping(self.buf.ping_response()?),
ResponseMsgType::SupplyKeypair => {
ResponseRef::SupplyKeypair(self.buf.supply_keypair_response()?)
}
ResponseMsgType::AddListenSocket => {
ResponseRef::AddListenSocket(self.buf.add_listen_socket_response()?)
}
ResponseMsgType::AddPskBroker => {
ResponseRef::AddPskBroker(self.buf.add_psk_broker_response()?)
}
})
}
#[allow(clippy::wrong_self_convention)]
fn from_prefix(self) -> anyhow::Result<Self> {
self.ensure_fit()?;
let point = self.target_size();
let Self { buf, msg_type } = self;
let (buf, _) = buf.split_at(point);
Ok(Self { buf, msg_type })
}
#[allow(clippy::wrong_self_convention)]
fn from_suffix(self) -> anyhow::Result<Self> {
self.ensure_fit()?;
let point = self.buf.len() - self.target_size();
let Self { buf, msg_type } = self;
let (buf, _) = buf.split_at(point);
Ok(Self { buf, msg_type })
}
pub fn ensure_fit(&self) -> anyhow::Result<()> {
let have = self.buf.len();
let need = self.target_size();
ensure!(
need <= have,
"Buffer is undersized at {have} bytes (need {need} bytes)!"
);
Ok(())
}
}
pub enum ResponseRef<B> {
Ping(Ref<B, PingResponse>),
SupplyKeypair(Ref<B, super::SupplyKeypairResponse>),
AddListenSocket(Ref<B, super::AddListenSocketResponse>),
AddPskBroker(Ref<B, super::AddPskBrokerResponse>),
}
impl<B> ResponseRef<B>
where
B: ByteSlice,
{
pub fn bytes(&self) -> &[u8] {
match self {
Self::Ping(r) => r.bytes(),
Self::SupplyKeypair(r) => r.bytes(),
Self::AddListenSocket(r) => r.bytes(),
Self::AddPskBroker(r) => r.bytes(),
}
}
}
impl<B> ResponseRef<B>
where
B: ByteSliceMut,
{
pub fn bytes_mut(&mut self) -> &[u8] {
match self {
Self::Ping(r) => r.bytes_mut(),
Self::SupplyKeypair(r) => r.bytes_mut(),
Self::AddListenSocket(r) => r.bytes_mut(),
Self::AddPskBroker(r) => r.bytes_mut(),
}
}
}

View File

@@ -0,0 +1,94 @@
use super::{ByteSliceRefExt, Message, PingRequest, PingResponse, RequestRef, RequestResponsePair};
use std::{collections::VecDeque, os::fd::OwnedFd};
use zerocopy::{ByteSlice, ByteSliceMut};
pub trait Server {
fn ping(
&mut self,
req: &PingRequest,
req_fds: &mut VecDeque<OwnedFd>,
res: &mut PingResponse,
) -> anyhow::Result<()>;
fn supply_keypair(
&mut self,
req: &super::SupplyKeypairRequest,
req_fds: &mut VecDeque<OwnedFd>,
res: &mut super::SupplyKeypairResponse,
) -> anyhow::Result<()>;
fn add_listen_socket(
&mut self,
req: &super::AddListenSocketRequest,
req_fds: &mut VecDeque<OwnedFd>,
res: &mut super::AddListenSocketResponse,
) -> anyhow::Result<()>;
fn add_psk_broker(
&mut self,
req: &super::AddPskBrokerRequest,
req_fds: &mut VecDeque<OwnedFd>,
res: &mut super::AddPskBrokerResponse,
) -> anyhow::Result<()>;
fn dispatch<ReqBuf, ResBuf>(
&mut self,
p: &mut RequestResponsePair<ReqBuf, ResBuf>,
req_fds: &mut VecDeque<OwnedFd>,
) -> anyhow::Result<()>
where
ReqBuf: ByteSlice,
ResBuf: ByteSliceMut,
{
match p {
RequestResponsePair::Ping((req, res)) => self.ping(req, req_fds, res),
RequestResponsePair::SupplyKeypair((req, res)) => {
self.supply_keypair(req, req_fds, res)
}
RequestResponsePair::AddListenSocket((req, res)) => {
self.add_listen_socket(req, req_fds, res)
}
RequestResponsePair::AddPskBroker((req, res)) => self.add_psk_broker(req, req_fds, res),
}
}
fn handle_message<ReqBuf, ResBuf>(
&mut self,
req: ReqBuf,
req_fds: &mut VecDeque<OwnedFd>,
res: ResBuf,
) -> anyhow::Result<usize>
where
ReqBuf: ByteSlice,
ResBuf: ByteSliceMut,
{
let req = req.parse_request_from_prefix()?;
// TODO: This is not pretty; This match should be moved into RequestRef
let mut pair = match req {
RequestRef::Ping(req) => {
let mut res = res.ping_response_from_prefix()?;
res.init();
RequestResponsePair::Ping((req, res))
}
RequestRef::SupplyKeypair(req) => {
let mut res = res.supply_keypair_response_from_prefix()?;
res.init();
RequestResponsePair::SupplyKeypair((req, res))
}
RequestRef::AddListenSocket(req) => {
let mut res = res.add_listen_socket_response_from_prefix()?;
res.init();
RequestResponsePair::AddListenSocket((req, res))
}
RequestRef::AddPskBroker(req) => {
let mut res = res.add_psk_broker_response_from_prefix()?;
res.init();
RequestResponsePair::AddPskBroker((req, res))
}
};
self.dispatch(&mut pair, req_fds)?;
let res_len = pair.response().bytes().len();
Ok(res_len)
}
}

40
rosenpass/src/api/cli.rs Normal file
View File

@@ -0,0 +1,40 @@
use std::path::PathBuf;
use clap::Args;
use crate::config::Rosenpass as RosenpassConfig;
use super::config::ApiConfig;
#[cfg(feature = "experiment_api")]
#[derive(Args, Debug)]
pub struct ApiCli {
/// Where in the file-system to create the unix socket the rosenpass API will be listening for
/// connections on.
#[arg(long)]
api_listen_path: Vec<PathBuf>,
/// When rosenpass is called from another process, the other process can open and bind the
/// unix socket for the Rosenpass API to use themselves, passing it to this process. In Rust this can be achieved
/// using the [command-fds](https://docs.rs/command-fds/latest/command_fds/) crate.
#[arg(long)]
api_listen_fd: Vec<i32>,
/// When rosenpass is called from another process, the other process can connect the unix socket for the API
/// themselves, for instance using the `socketpair(2)` system call.
#[arg(long)]
api_stream_fd: Vec<i32>,
}
impl ApiCli {
pub fn apply_to_config(&self, cfg: &mut RosenpassConfig) -> anyhow::Result<()> {
self.apply_to_api_config(&mut cfg.api)
}
pub fn apply_to_api_config(&self, cfg: &mut ApiConfig) -> anyhow::Result<()> {
cfg.listen_path.extend_from_slice(&self.api_listen_path);
cfg.listen_fd.extend_from_slice(&self.api_listen_fd);
cfg.stream_fd.extend_from_slice(&self.api_stream_fd);
Ok(())
}
}

View File

@@ -0,0 +1,49 @@
use std::path::PathBuf;
use mio::net::UnixListener;
use rosenpass_util::mio::{UnixListenerExt, UnixStreamExt};
use serde::{Deserialize, Serialize};
use crate::app_server::AppServer;
#[derive(Debug, Serialize, Deserialize, Default, Clone)]
pub struct ApiConfig {
/// Where in the file-system to create the unix socket the rosenpass API will be listening for
/// connections on
pub listen_path: Vec<PathBuf>,
/// When rosenpass is called from another process, the other process can open and bind the
/// unix socket for the Rosenpass API to use themselves, passing it to this process. In Rust this can be achieved
/// using the [command-fds](https://docs.rs/command-fds/latest/command_fds/) crate.
pub listen_fd: Vec<i32>,
/// When rosenpass is called from another process, the other process can connect the unix socket for the API
/// themselves, for instance using the `socketpair(2)` system call.
pub stream_fd: Vec<i32>,
}
impl ApiConfig {
pub fn apply_to_app_server(&self, srv: &mut AppServer) -> anyhow::Result<()> {
for path in self.listen_path.iter() {
srv.add_api_listener(UnixListener::bind(path)?)?;
}
for fd in self.listen_fd.iter() {
srv.add_api_listener(UnixListenerExt::claim_fd(*fd)?)?;
}
for fd in self.stream_fd.iter() {
srv.add_api_connection(UnixStreamExt::claim_fd(*fd)?)?;
}
Ok(())
}
pub fn count_api_sources(&self) -> usize {
self.listen_path.len() + self.listen_fd.len() + self.stream_fd.len()
}
pub fn has_api_sources(&self) -> bool {
self.count_api_sources() > 0
}
}

View File

@@ -0,0 +1,321 @@
use std::borrow::{Borrow, BorrowMut};
use std::collections::VecDeque;
use std::os::fd::OwnedFd;
use mio::net::UnixStream;
use rosenpass_secret_memory::Secret;
use rosenpass_util::mio::ReadWithFileDescriptors;
use rosenpass_util::{
io::{IoResultKindHintExt, TryIoResultKindHintExt},
length_prefix_encoding::{
decoder::{self as lpe_decoder, LengthPrefixDecoder},
encoder::{self as lpe_encoder, LengthPrefixEncoder},
},
mio::interest::RW as MIO_RW,
};
use zeroize::Zeroize;
use crate::api::MAX_REQUEST_FDS;
use crate::{api::Server, app_server::AppServer};
use super::super::{ApiHandler, ApiHandlerContext};
#[derive(Debug)]
struct SecretBuffer<const N: usize>(pub Secret<N>);
impl<const N: usize> SecretBuffer<N> {
fn new() -> Self {
Self(Secret::zero())
}
}
impl<const N: usize> Borrow<[u8]> for SecretBuffer<N> {
fn borrow(&self) -> &[u8] {
self.0.secret()
}
}
impl<const N: usize> BorrowMut<[u8]> for SecretBuffer<N> {
fn borrow_mut(&mut self) -> &mut [u8] {
self.0.secret_mut()
}
}
// TODO: Unfortunately, zerocopy is quite particular about alignment, hence the 4096
type ReadBuffer = LengthPrefixDecoder<SecretBuffer<4096>>;
type WriteBuffer = LengthPrefixEncoder<SecretBuffer<4096>>;
type ReadFdBuffer = VecDeque<OwnedFd>;
#[derive(Debug)]
struct MioConnectionBuffers {
read_buffer: ReadBuffer,
write_buffer: WriteBuffer,
read_fd_buffer: ReadFdBuffer,
}
#[derive(Debug)]
pub struct MioConnection {
io: UnixStream,
mio_token: mio::Token,
invalid_read: bool,
buffers: Option<MioConnectionBuffers>,
api_handler: ApiHandler,
}
impl MioConnection {
pub fn new(app_server: &mut AppServer, mut io: UnixStream) -> std::io::Result<Self> {
let mio_token = app_server.mio_token_dispenser.dispense();
app_server
.mio_poll
.registry()
.register(&mut io, mio_token, MIO_RW)?;
let invalid_read = false;
let read_buffer = LengthPrefixDecoder::new(SecretBuffer::new());
let write_buffer = LengthPrefixEncoder::from_buffer(SecretBuffer::new());
let read_fd_buffer = VecDeque::new();
let buffers = Some(MioConnectionBuffers {
read_buffer,
write_buffer,
read_fd_buffer,
});
let api_state = ApiHandler::new();
Ok(Self {
io,
mio_token,
invalid_read,
buffers,
api_handler: api_state,
})
}
pub fn shoud_close(&self) -> bool {
let exhausted = self
.buffers
.as_ref()
.map(|b| b.write_buffer.exhausted())
.unwrap_or(false);
self.invalid_read && exhausted
}
pub fn close(mut self, app_server: &mut AppServer) -> anyhow::Result<()> {
app_server.mio_poll.registry().deregister(&mut self.io)?;
Ok(())
}
pub fn mio_token(&self) -> mio::Token {
self.mio_token
}
}
pub trait MioConnectionContext {
fn mio_connection(&self) -> &MioConnection;
fn app_server(&self) -> &AppServer;
fn mio_connection_mut(&mut self) -> &mut MioConnection;
fn app_server_mut(&mut self) -> &mut AppServer;
fn poll(&mut self) -> anyhow::Result<()> {
macro_rules! short {
($e:expr) => {
match $e {
None => return Ok(()),
Some(()) => {}
}
};
}
// All of these functions return an error, None ("operation incomplete")
// or some ("operation complete, keep processing")
short!(self.flush_write_buffer()?); // Flush last message
short!(self.recv()?); // Receive new message
short!(self.handle_incoming_message()?); // Process new message with API
short!(self.flush_write_buffer()?); // Begin flushing response
Ok(())
}
fn handle_incoming_message(&mut self) -> anyhow::Result<Option<()>> {
self.with_buffers_stolen(|this, bufs| {
// Acquire request & response. Caller is responsible to make sure
// that read buffer holds a message and that write buffer is cleared.
// Hence the unwraps and assertions
assert!(bufs.write_buffer.exhausted());
let req = bufs.read_buffer.message().unwrap().unwrap();
let req_fds = &mut bufs.read_fd_buffer;
let res = bufs.write_buffer.buffer_bytes_mut();
// Call API handler
// Transitive trait implementations: MioConnectionContext -> ApiHandlerContext -> as ApiServer
let response_len = this.handle_message(req, req_fds, res)?;
bufs.write_buffer
.restart_write_with_new_message(response_len)?;
bufs.read_buffer.zeroize(); // clear for new message to read
bufs.read_fd_buffer.clear();
Ok(Some(()))
})
}
fn flush_write_buffer(&mut self) -> anyhow::Result<Option<()>> {
if self.write_buf_mut().exhausted() {
return Ok(Some(()));
}
use lpe_encoder::WriteToIoReturn as Ret;
use std::io::ErrorKind as K;
loop {
let conn = self.mio_connection_mut();
let bufs = conn.buffers.as_mut().unwrap();
let sock = &conn.io;
let write_buf = &mut bufs.write_buffer;
match write_buf.write_to_stdio(sock).io_err_kind_hint() {
// Done
Ok(Ret { done: true, .. }) => {
write_buf.zeroize(); // clear for new message to write
break Ok(Some(()));
}
// Would block
Ok(Ret {
bytes_written: 0, ..
}) => break Ok(None),
Err((_e, K::WouldBlock)) => break Ok(None),
// Just continue
Ok(_) => continue, /* Ret { bytes_written > 0, done = false } acc. to previous cases*/
Err((_e, K::Interrupted)) => continue,
// Other errors
Err((e, _ek)) => Err(e)?,
}
}
}
fn recv(&mut self) -> anyhow::Result<Option<()>> {
if !self.write_buf_mut().exhausted() || self.mio_connection().invalid_read {
return Ok(None);
}
use lpe_decoder::{ReadFromIoError as E, ReadFromIoReturn as Ret};
use std::io::ErrorKind as K;
loop {
let conn = self.mio_connection_mut();
let bufs = conn.buffers.as_mut().unwrap();
let read_buf = &mut bufs.read_buffer;
let read_fd_buf = &mut bufs.read_fd_buffer;
let sock = &conn.io;
let fd_passing_sock = ReadWithFileDescriptors::<MAX_REQUEST_FDS, UnixStream, _, _>::new(
sock,
read_fd_buf,
);
match read_buf
.read_from_stdio(fd_passing_sock)
.try_io_err_kind_hint()
{
// We actually received a proper message
// (Impl below match to appease borrow checker)
Ok(Ret {
message: Some(_msg),
..
}) => break Ok(Some(())),
// Message does not fit in buffer
Err((e @ E::MessageTooLargeError { .. }, _)) => {
log::warn!("Received message on API that was too big to fit in our buffers; \
looks like the client is broken. Stopping to process messages of the client.\n\
Error: {e:?}");
conn.invalid_read = true; // Closed mio_manager
break Ok(None);
}
// Would block
Ok(Ret { bytes_read: 0, .. }) => break Ok(None),
Err((_, Some(K::WouldBlock))) => break Ok(None),
// Just keep going
Ok(Ret { bytes_read: _, .. }) => continue,
Err((_, Some(K::Interrupted))) => continue,
// Other IO Error (just pass on to the caller)
Err((E::IoError(e), _)) => {
log::warn!(
"IO error while trying to read message from API socket. \
The connection is broken. Stopping to process messages of the client.\n\
Error: {e:?}"
);
conn.invalid_read = true; // closed later by mio_manager
break Err(e.into());
}
};
}
}
fn mio_token(&self) -> mio::Token {
self.mio_connection().mio_token()
}
fn should_close(&self) -> bool {
self.mio_connection().shoud_close()
}
}
trait MioConnectionContextPrivate: MioConnectionContext {
fn steal_buffers(&mut self) -> MioConnectionBuffers {
self.mio_connection_mut().buffers.take().unwrap()
}
fn return_buffers(&mut self, buffers: MioConnectionBuffers) {
let opt = &mut self.mio_connection_mut().buffers;
assert!(opt.is_none());
let _ = opt.insert(buffers);
}
fn with_buffers_stolen<R, F: FnOnce(&mut Self, &mut MioConnectionBuffers) -> R>(
&mut self,
f: F,
) -> R {
let mut bufs = self.steal_buffers();
let res = f(self, &mut bufs);
self.return_buffers(bufs);
res
}
fn write_buf_mut(&mut self) -> &mut WriteBuffer {
self.mio_connection_mut()
.buffers
.as_mut()
.unwrap()
.write_buffer
.borrow_mut()
}
}
impl<T> MioConnectionContextPrivate for T where T: ?Sized + MioConnectionContext {}
impl<T> ApiHandlerContext for T
where
T: ?Sized + MioConnectionContext,
{
fn api_handler(&self) -> &ApiHandler {
&self.mio_connection().api_handler
}
fn app_server(&self) -> &AppServer {
MioConnectionContext::app_server(self)
}
fn api_handler_mut(&mut self) -> &mut ApiHandler {
&mut self.mio_connection_mut().api_handler
}
fn app_server_mut(&mut self) -> &mut AppServer {
MioConnectionContext::app_server_mut(self)
}
}

View File

@@ -0,0 +1,173 @@
use std::{borrow::BorrowMut, io};
use mio::net::{UnixListener, UnixStream};
use rosenpass_util::{
functional::ApplyExt, io::nonblocking_handle_io_errors, mio::interest::RW as MIO_RW,
};
use crate::app_server::{AppServer, AppServerIoSource};
use super::{MioConnection, MioConnectionContext};
#[derive(Default, Debug)]
pub struct MioManager {
listeners: Vec<UnixListener>,
connections: Vec<Option<MioConnection>>,
}
#[derive(Debug, PartialEq, Eq, Copy, Clone)]
pub enum MioManagerIoSource {
Listener(usize),
Connection(usize),
}
impl MioManager {
pub fn new() -> Self {
Self::default()
}
}
struct MioConnectionFocus<'a, T: ?Sized + MioManagerContext> {
ctx: &'a mut T,
conn_idx: usize,
}
impl<'a, T: ?Sized + MioManagerContext> MioConnectionFocus<'a, T> {
fn new(ctx: &'a mut T, conn_idx: usize) -> Self {
Self { ctx, conn_idx }
}
}
pub trait MioManagerContext {
fn mio_manager(&self) -> &MioManager;
fn mio_manager_mut(&mut self) -> &mut MioManager;
fn app_server(&self) -> &AppServer;
fn app_server_mut(&mut self) -> &mut AppServer;
fn add_listener(&mut self, mut listener: UnixListener) -> io::Result<()> {
let srv = self.app_server_mut();
let mio_token = srv.mio_token_dispenser.dispense();
srv.mio_poll
.registry()
.register(&mut listener, mio_token, MIO_RW)?;
let io_source = self
.mio_manager()
.listeners
.len()
.apply(MioManagerIoSource::Listener)
.apply(AppServerIoSource::MioManager);
self.mio_manager_mut().listeners.push(listener);
self.app_server_mut()
.register_io_source(mio_token, io_source);
Ok(())
}
fn add_connection(&mut self, connection: UnixStream) -> io::Result<()> {
let connection = MioConnection::new(self.app_server_mut(), connection)?;
let mio_token = connection.mio_token();
let conns: &mut Vec<Option<MioConnection>> =
self.mio_manager_mut().connections.borrow_mut();
let idx = conns
.iter_mut()
.enumerate()
.find(|(_, slot)| slot.is_some())
.map(|(idx, _)| idx)
.unwrap_or(conns.len());
conns.insert(idx, Some(connection));
let io_source = idx
.apply(MioManagerIoSource::Listener)
.apply(AppServerIoSource::MioManager);
self.app_server_mut()
.register_io_source(mio_token, io_source);
Ok(())
}
fn poll_particular(&mut self, io_source: MioManagerIoSource) -> anyhow::Result<()> {
use MioManagerIoSource as S;
match io_source {
S::Listener(idx) => self.accept_from(idx)?,
S::Connection(idx) => self.poll_particular_connection(idx)?,
};
Ok(())
}
fn poll(&mut self) -> anyhow::Result<()> {
self.accept_connections()?;
self.poll_connections()?;
Ok(())
}
fn accept_connections(&mut self) -> io::Result<()> {
for idx in 0..self.mio_manager_mut().listeners.len() {
self.accept_from(idx)?;
}
Ok(())
}
fn accept_from(&mut self, idx: usize) -> io::Result<()> {
// Accept connection until the socket would block or returns another error
// TODO: This currently only adds connections--we eventually need the ability to remove
// them as well, see the note in connection.rs
loop {
match nonblocking_handle_io_errors(|| self.mio_manager().listeners[idx].accept())? {
None => break,
Some((conn, _addr)) => {
self.add_connection(conn)?;
}
};
}
Ok(())
}
fn poll_connections(&mut self) -> anyhow::Result<()> {
for idx in 0..self.mio_manager().connections.len() {
self.poll_particular_connection(idx)?;
}
Ok(())
}
fn poll_particular_connection(&mut self, idx: usize) -> anyhow::Result<()> {
if self.mio_manager().connections[idx].is_none() {
return Ok(());
}
let mut conn = MioConnectionFocus::new(self, idx);
conn.poll()?;
if conn.should_close() {
let conn = self.mio_manager_mut().connections[idx].take().unwrap();
let mio_token = conn.mio_token();
if let Err(e) = conn.close(self.app_server_mut()) {
log::warn!("Error while closing API connection {e:?}");
};
self.app_server_mut().unregister_io_source(mio_token);
}
Ok(())
}
}
impl<T: ?Sized + MioManagerContext> MioConnectionContext for MioConnectionFocus<'_, T> {
fn mio_connection(&self) -> &MioConnection {
self.ctx.mio_manager().connections[self.conn_idx]
.as_ref()
.unwrap()
}
fn app_server(&self) -> &AppServer {
self.ctx.app_server()
}
fn mio_connection_mut(&mut self) -> &mut MioConnection {
self.ctx.mio_manager_mut().connections[self.conn_idx]
.as_mut()
.unwrap()
}
fn app_server_mut(&mut self) -> &mut AppServer {
self.ctx.app_server_mut()
}
}

View File

@@ -0,0 +1,5 @@
mod connection;
mod manager;
pub use connection::*;
pub use manager::*;

9
rosenpass/src/api/mod.rs Normal file
View File

@@ -0,0 +1,9 @@
mod api_handler;
mod boilerplate;
pub use api_handler::*;
pub use boilerplate::*;
pub mod cli;
pub mod config;
pub mod mio;

Some files were not shown because too many files have changed in this diff Show More