Compare commits
1 Commits
dev/karo/a
...
whitepaper
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
4fbcf3f568 |
@@ -1,14 +0,0 @@
|
|||||||
public_key = "rp-a-public-key"
|
|
||||||
secret_key = "rp-a-secret-key"
|
|
||||||
listen = ["127.0.0.1:9999"]
|
|
||||||
verbosity = "Verbose"
|
|
||||||
|
|
||||||
[api]
|
|
||||||
listen_path = []
|
|
||||||
listen_fd = []
|
|
||||||
stream_fd = []
|
|
||||||
|
|
||||||
[[peers]]
|
|
||||||
public_key = "rp-b-public-key"
|
|
||||||
endpoint = "127.0.0.1:9998"
|
|
||||||
key_out = "rp-b-key-out.txt"
|
|
||||||
@@ -1,14 +0,0 @@
|
|||||||
public_key = "rp-b-public-key"
|
|
||||||
secret_key = "rp-b-secret-key"
|
|
||||||
listen = ["127.0.0.1:9998"]
|
|
||||||
verbosity = "Verbose"
|
|
||||||
|
|
||||||
[api]
|
|
||||||
listen_path = []
|
|
||||||
listen_fd = []
|
|
||||||
stream_fd = []
|
|
||||||
|
|
||||||
[[peers]]
|
|
||||||
public_key = "rp-a-public-key"
|
|
||||||
endpoint = "127.0.0.1:9999"
|
|
||||||
key_out = "rp-a-key-out.txt"
|
|
||||||
@@ -1,48 +0,0 @@
|
|||||||
#!/bin/bash
|
|
||||||
|
|
||||||
iterations="$1"
|
|
||||||
sleep_time="$2"
|
|
||||||
config_a="$3"
|
|
||||||
config_b="$4"
|
|
||||||
|
|
||||||
PWD="$(pwd)"
|
|
||||||
EXEC="$PWD/target/release/rosenpass"
|
|
||||||
|
|
||||||
i=0
|
|
||||||
while [ "$i" -ne "$iterations" ]; do
|
|
||||||
echo "=> Iteration $i"
|
|
||||||
|
|
||||||
# flush the PSK files
|
|
||||||
echo "A" >rp-a-key-out.txt
|
|
||||||
echo "B" >rp-b-key-out.txt
|
|
||||||
|
|
||||||
# start the two instances
|
|
||||||
echo "Starting instance A"
|
|
||||||
"$EXEC" exchange-config "$config_a" &
|
|
||||||
PID_A=$!
|
|
||||||
sleep "$sleep_time"
|
|
||||||
echo "Starting instance B"
|
|
||||||
"$EXEC" exchange-config "$config_b" &
|
|
||||||
PID_B=$!
|
|
||||||
|
|
||||||
# give the key exchange some time to complete
|
|
||||||
sleep 3
|
|
||||||
|
|
||||||
# kill the instances
|
|
||||||
kill $PID_A
|
|
||||||
kill $PID_B
|
|
||||||
|
|
||||||
# compare the keys
|
|
||||||
if cmp -s rp-a-key-out.txt rp-b-key-out.txt; then
|
|
||||||
echo "Keys match"
|
|
||||||
else
|
|
||||||
echo "::warning title=Key Exchange Race Condition::The key exchange resulted in different keys. Delay was ${sleep_time}s."
|
|
||||||
# TODO: set this to 1 when the race condition is fixed
|
|
||||||
exit 0
|
|
||||||
fi
|
|
||||||
|
|
||||||
# give the instances some time to shut down
|
|
||||||
sleep 2
|
|
||||||
|
|
||||||
i=$((i + 1))
|
|
||||||
done
|
|
||||||
@@ -1,201 +0,0 @@
|
|||||||
#!/usr/bin/env nu
|
|
||||||
|
|
||||||
use std log
|
|
||||||
|
|
||||||
# cd to git root
|
|
||||||
cd (git rev-parse --show-toplevel)
|
|
||||||
|
|
||||||
# check if a subject depends on a potential dependency
|
|
||||||
def depends [
|
|
||||||
subject:string # package to examine
|
|
||||||
maybe_dep:string # maybe a dependency of subject
|
|
||||||
] {
|
|
||||||
not ( nix why-depends --quiet --derivation $subject $maybe_dep | is-empty )
|
|
||||||
}
|
|
||||||
|
|
||||||
# get attribute names of the attribute set
|
|
||||||
def get-attr-names [
|
|
||||||
expr: # nix expression to get attrNames of
|
|
||||||
] {
|
|
||||||
nix eval --json $expr --apply builtins.attrNames | from json
|
|
||||||
}
|
|
||||||
|
|
||||||
def job-id [
|
|
||||||
system:string,
|
|
||||||
derivation:string,
|
|
||||||
] {
|
|
||||||
$"($system)---($derivation)"
|
|
||||||
}
|
|
||||||
|
|
||||||
# map from nixos system to github runner type
|
|
||||||
let systems_map = {
|
|
||||||
# aarch64-darwin
|
|
||||||
# aarch64-linux
|
|
||||||
|
|
||||||
i686-linux: ubuntu-latest,
|
|
||||||
x86_64-darwin: macos-13,
|
|
||||||
x86_64-linux: ubuntu-latest
|
|
||||||
}
|
|
||||||
|
|
||||||
let targets = (get-attr-names ".#packages"
|
|
||||||
| par-each {|system| { $system : (get-attr-names $".#packages.($system)") } }
|
|
||||||
| reduce {|it, acc| $acc | merge $it }
|
|
||||||
)
|
|
||||||
|
|
||||||
mut cachix_workflow = {
|
|
||||||
name: "Nix",
|
|
||||||
permissions: {contents: write},
|
|
||||||
on: {
|
|
||||||
pull_request: null,
|
|
||||||
push: {branches: [main]}
|
|
||||||
},
|
|
||||||
jobs: {},
|
|
||||||
}
|
|
||||||
|
|
||||||
mut release_workflow = {
|
|
||||||
name: "Release",
|
|
||||||
permissions: {contents: write},
|
|
||||||
on: { push: {tags: ["v*"]} },
|
|
||||||
jobs: {},
|
|
||||||
}
|
|
||||||
|
|
||||||
let runner_setup = [
|
|
||||||
{
|
|
||||||
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 }}"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
]
|
|
||||||
|
|
||||||
for system in ($targets | columns) {
|
|
||||||
if ($systems_map | get -i $system | is-empty) {
|
|
||||||
log info $"skipping ($system), since there are no GH-Actions runners for it"
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
# lookup the correct runner for $system
|
|
||||||
let runs_on = [ ($systems_map | get $system) ]
|
|
||||||
|
|
||||||
# add jobs for all derivations
|
|
||||||
let derivations = ($targets | get $system)
|
|
||||||
for derivation in $derivations {
|
|
||||||
|
|
||||||
if ($system == "i686-linux") and ($derivation | str contains "static") {
|
|
||||||
log info $"skipping ($system).($derivation), due to liboqs 0.8 not present in oqs-sys"
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($system == "i686-linux") and ($derivation | str contains "release-package") {
|
|
||||||
log info $"skipping ($system).($derivation), due to liboqs 0.8 not present in oqs-sys"
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
# job_id for GH-Actions
|
|
||||||
let id = ( job-id $system $derivation )
|
|
||||||
|
|
||||||
# name displayed
|
|
||||||
let name = $"($system).($derivation)"
|
|
||||||
|
|
||||||
# collection of dependencies
|
|
||||||
# TODO currently only considers dependencies on the same $system
|
|
||||||
let needs = ($derivations
|
|
||||||
| filter {|it| $it != $derivation and $it != "default" } # filter out self and default
|
|
||||||
| par-each {|it| {
|
|
||||||
name: $it, # the other derivation
|
|
||||||
# does self depend on $it?
|
|
||||||
needed: (depends $".#packages.($system).($derivation)" $".#packages.($system).($it)")
|
|
||||||
} }
|
|
||||||
| filter {|it| $it.needed}
|
|
||||||
| each {|it| job-id $system $it.name}
|
|
||||||
| sort
|
|
||||||
)
|
|
||||||
|
|
||||||
mut new_job = {
|
|
||||||
name: $"Build ($name)",
|
|
||||||
"runs-on": $runs_on,
|
|
||||||
needs: $needs,
|
|
||||||
steps: ($runner_setup | append [
|
|
||||||
{
|
|
||||||
name: Build,
|
|
||||||
run: $"nix build .#packages.($system).($derivation) --print-build-logs"
|
|
||||||
}
|
|
||||||
])
|
|
||||||
}
|
|
||||||
$cachix_workflow.jobs = ($cachix_workflow.jobs | insert $id $new_job )
|
|
||||||
}
|
|
||||||
|
|
||||||
# add check job
|
|
||||||
$cachix_workflow.jobs = ($cachix_workflow.jobs | insert $"($system)---check" {
|
|
||||||
name: $"Run Nix checks on ($system)",
|
|
||||||
"runs-on": $runs_on,
|
|
||||||
steps: ($runner_setup | append {
|
|
||||||
name: Check,
|
|
||||||
run: "nix flake check . --print-build-logs"
|
|
||||||
})
|
|
||||||
})
|
|
||||||
|
|
||||||
# add release job
|
|
||||||
$release_workflow.jobs = ($release_workflow.jobs | insert $"($system)---release" {
|
|
||||||
name: $"Build release artifacts for ($system)",
|
|
||||||
"runs-on": $runs_on,
|
|
||||||
steps: ($runner_setup | append [
|
|
||||||
{
|
|
||||||
name: "Build release",
|
|
||||||
run: "nix build .#release-package --print-build-logs"
|
|
||||||
}
|
|
||||||
{
|
|
||||||
name: Release,
|
|
||||||
uses: "softprops/action-gh-release@v1",
|
|
||||||
with: {
|
|
||||||
draft: "${{ contains(github.ref_name, 'rc') }}",
|
|
||||||
prerelease: "${{ contains(github.ref_name, 'alpha') || contains(github.ref_name, 'beta') }}",
|
|
||||||
files: "result/*"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
])
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
# add whitepaper job with upload
|
|
||||||
let system = "x86_64-linux"
|
|
||||||
$cachix_workflow.jobs = ($cachix_workflow.jobs | insert $"($system)---whitepaper-upload" {
|
|
||||||
name: $"Upload whitepaper ($system)",
|
|
||||||
"runs-on": ($systems_map | get $system),
|
|
||||||
"if": "${{ github.ref == 'refs/heads/main' }}",
|
|
||||||
steps: ($runner_setup | append [
|
|
||||||
{
|
|
||||||
name: "Git add git sha and commit",
|
|
||||||
run: "cd papers && ./tex/gitinfo2.sh && git add gitHeadInfo.gin"
|
|
||||||
}
|
|
||||||
{
|
|
||||||
name: Build,
|
|
||||||
run: $"nix build .#packages.($system).whitepaper --print-build-logs"
|
|
||||||
}
|
|
||||||
{
|
|
||||||
name: "Deploy PDF artifacts",
|
|
||||||
uses: "peaceiris/actions-gh-pages@v3",
|
|
||||||
with: {
|
|
||||||
github_token: "${{ secrets.GITHUB_TOKEN }}",
|
|
||||||
publish_dir: result/,
|
|
||||||
publish_branch: papers-pdf,
|
|
||||||
force_orphan: true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
])
|
|
||||||
})
|
|
||||||
|
|
||||||
log info "saving nix-cachix workflow"
|
|
||||||
$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/
|
|
||||||
@@ -1,33 +0,0 @@
|
|||||||
#!/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 +0,0 @@
|
|||||||
FROM ghcr.io/xtruder/nix-devcontainer:v1
|
|
||||||
@@ -1,33 +0,0 @@
|
|||||||
// 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
@@ -1,14 +0,0 @@
|
|||||||
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
|
|
||||||
10
.github/dependabot.yml
vendored
@@ -1,10 +0,0 @@
|
|||||||
version: 2
|
|
||||||
updates:
|
|
||||||
- package-ecosystem: "cargo"
|
|
||||||
directory: "/"
|
|
||||||
schedule:
|
|
||||||
interval: "daily"
|
|
||||||
- package-ecosystem: "github-actions"
|
|
||||||
directory: "/"
|
|
||||||
schedule:
|
|
||||||
interval: "daily"
|
|
||||||
63
.github/workflows/dependent-issues.yml
vendored
@@ -1,63 +0,0 @@
|
|||||||
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!
|
|
||||||
49
.github/workflows/doc-upload.yml
vendored
@@ -1,49 +0,0 @@
|
|||||||
name: Update website docs
|
|
||||||
|
|
||||||
on:
|
|
||||||
push:
|
|
||||||
branches:
|
|
||||||
- main
|
|
||||||
paths:
|
|
||||||
- "doc/**"
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
update-website:
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
|
|
||||||
steps:
|
|
||||||
- name: Checkout code
|
|
||||||
uses: actions/checkout@v4
|
|
||||||
|
|
||||||
- name: Clone rosenpass-website repository
|
|
||||||
uses: actions/checkout@v4
|
|
||||||
with:
|
|
||||||
repository: rosenpass/rosenpass-website
|
|
||||||
ref: main
|
|
||||||
path: rosenpass-website
|
|
||||||
token: ${{ secrets.PRIVACC }}
|
|
||||||
|
|
||||||
- name: Copy docs to website repo
|
|
||||||
run: |
|
|
||||||
cp -R doc/* rosenpass-website/static/docs/
|
|
||||||
|
|
||||||
- name: Install mandoc
|
|
||||||
run: |
|
|
||||||
sudo apt-get update
|
|
||||||
sudo apt-get install -y mandoc
|
|
||||||
|
|
||||||
- name: Compile man pages to HTML
|
|
||||||
run: |
|
|
||||||
cd rosenpass-website/static/docs/
|
|
||||||
for file in *.1; do
|
|
||||||
mandoc -Thtml "$file" > "${file%.*}.html"
|
|
||||||
done
|
|
||||||
|
|
||||||
- name: Commit changes to website repo
|
|
||||||
uses: EndBug/add-and-commit@v9
|
|
||||||
with:
|
|
||||||
author_name: GitHub Actions
|
|
||||||
author_email: actions@github.com
|
|
||||||
message: Update docs
|
|
||||||
cwd: rosenpass-website/static/docs
|
|
||||||
github_token: ${{ secrets.PRIVACC }
|
|
||||||
519
.github/workflows/nix.yaml
vendored
@@ -1,473 +1,74 @@
|
|||||||
name: Nix
|
name: Nix Related Actions
|
||||||
permissions:
|
permissions:
|
||||||
contents: write
|
contents: write
|
||||||
on:
|
on:
|
||||||
pull_request: null
|
pull_request:
|
||||||
push:
|
push:
|
||||||
branches:
|
branches: [main]
|
||||||
- main
|
|
||||||
|
|
||||||
concurrency:
|
|
||||||
group: ${{ github.workflow }}-${{ github.ref }}
|
|
||||||
cancel-in-progress: true
|
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
i686-linux---default:
|
build:
|
||||||
name: Build i686-linux.default
|
name: Build ${{ matrix.derivation }} on ${{ matrix.nix-system }}
|
||||||
runs-on:
|
runs-on:
|
||||||
- ubuntu-latest
|
- nix
|
||||||
needs:
|
- ${{ matrix.nix-system }}
|
||||||
- i686-linux---rosenpass
|
strategy:
|
||||||
|
fail-fast: false
|
||||||
|
matrix:
|
||||||
|
nix-system:
|
||||||
|
- x86_64-linux
|
||||||
|
# - aarch64-linux
|
||||||
|
derivation:
|
||||||
|
- rosenpass
|
||||||
|
- rosenpass-static
|
||||||
|
- rosenpass-oci-image
|
||||||
|
- rosenpass-static-oci-image
|
||||||
|
- proof-proverif
|
||||||
|
- whitepaper
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v3
|
||||||
- uses: cachix/install-nix-action@v30
|
- name: Generate gitHeadInfo.gin for the whitepaper
|
||||||
|
if: ${{ matrix.derivation == 'whitepaper' }}
|
||||||
|
run: ( cd papers && ./tex/gitinfo2.sh && git add gitHeadInfo.gin )
|
||||||
|
- name: Build ${{ matrix.derivation }}@${{ matrix.nix-system }}
|
||||||
|
run: |
|
||||||
|
# build the package
|
||||||
|
nix build .#packages.${{ matrix.nix-system }}.${{ matrix.derivation }} --print-build-logs
|
||||||
|
|
||||||
|
# copy over the results
|
||||||
|
if [[ -f $(readlink --canonicalize result ) ]]; then
|
||||||
|
mkdir -- ${{ matrix.derivation }}-${{ matrix.nix-system }}
|
||||||
|
fi
|
||||||
|
cp --recursive -- $(readlink --canonicalize result) ${{ matrix.derivation }}-${{ matrix.nix-system }}
|
||||||
|
chmod --recursive ug+rw -- ${{ matrix.derivation }}-${{ matrix.nix-system }}
|
||||||
|
|
||||||
|
# add version information
|
||||||
|
git rev-parse --abbrev-ref HEAD > ${{ matrix.derivation }}-${{ matrix.nix-system }}/git-version
|
||||||
|
git rev-parse HEAD > ${{ matrix.derivation }}-${{ matrix.nix-system }}/git-sha
|
||||||
|
|
||||||
|
# override the `rp` script to keep compatible with non-nix systems
|
||||||
|
if [[ -f ${{ matrix.derivation }}-${{ matrix.nix-system }}/bin/rp ]]; then
|
||||||
|
cp --force -- rp ${{ matrix.derivation }}-${{ matrix.nix-system }}/bin/
|
||||||
|
fi
|
||||||
|
- name: Upload build results
|
||||||
|
uses: actions/upload-artifact@v3
|
||||||
with:
|
with:
|
||||||
nix_path: nixpkgs=channel:nixos-unstable
|
name: ${{ matrix.derivation }}-${{ matrix.nix-system }}
|
||||||
- uses: cachix/cachix-action@v15
|
path: ${{ matrix.derivation }}-${{ matrix.nix-system }}
|
||||||
with:
|
|
||||||
name: rosenpass
|
|
||||||
authToken: ${{ secrets.CACHIX_AUTH_TOKEN }}
|
|
||||||
- name: Build
|
|
||||||
run: nix build .#packages.i686-linux.default --print-build-logs
|
|
||||||
i686-linux---rosenpass:
|
|
||||||
name: Build i686-linux.rosenpass
|
|
||||||
runs-on:
|
|
||||||
- ubuntu-latest
|
|
||||||
needs: []
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v4
|
|
||||||
- uses: cachix/install-nix-action@v30
|
|
||||||
with:
|
|
||||||
nix_path: nixpkgs=channel:nixos-unstable
|
|
||||||
- uses: cachix/cachix-action@v15
|
|
||||||
with:
|
|
||||||
name: rosenpass
|
|
||||||
authToken: ${{ secrets.CACHIX_AUTH_TOKEN }}
|
|
||||||
- name: Build
|
|
||||||
run: nix build .#packages.i686-linux.rosenpass --print-build-logs
|
|
||||||
i686-linux---rosenpass-oci-image:
|
|
||||||
name: Build i686-linux.rosenpass-oci-image
|
|
||||||
runs-on:
|
|
||||||
- ubuntu-latest
|
|
||||||
needs:
|
|
||||||
- i686-linux---rosenpass
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v4
|
|
||||||
- uses: cachix/install-nix-action@v30
|
|
||||||
with:
|
|
||||||
nix_path: nixpkgs=channel:nixos-unstable
|
|
||||||
- uses: cachix/cachix-action@v15
|
|
||||||
with:
|
|
||||||
name: rosenpass
|
|
||||||
authToken: ${{ secrets.CACHIX_AUTH_TOKEN }}
|
|
||||||
- name: Build
|
|
||||||
run: nix build .#packages.i686-linux.rosenpass-oci-image --print-build-logs
|
|
||||||
i686-linux---check:
|
|
||||||
name: Run Nix checks on i686-linux
|
|
||||||
runs-on:
|
|
||||||
- ubuntu-latest
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v4
|
|
||||||
- uses: cachix/install-nix-action@v30
|
|
||||||
with:
|
|
||||||
nix_path: nixpkgs=channel:nixos-unstable
|
|
||||||
- uses: cachix/cachix-action@v15
|
|
||||||
with:
|
|
||||||
name: rosenpass
|
|
||||||
authToken: ${{ secrets.CACHIX_AUTH_TOKEN }}
|
|
||||||
- name: Check
|
|
||||||
run: nix flake check . --print-build-logs
|
|
||||||
x86_64-darwin---default:
|
|
||||||
name: Build x86_64-darwin.default
|
|
||||||
runs-on:
|
|
||||||
- macos-13
|
|
||||||
needs:
|
|
||||||
- x86_64-darwin---rosenpass
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v4
|
|
||||||
- uses: cachix/install-nix-action@v30
|
|
||||||
with:
|
|
||||||
nix_path: nixpkgs=channel:nixos-unstable
|
|
||||||
- uses: cachix/cachix-action@v15
|
|
||||||
with:
|
|
||||||
name: rosenpass
|
|
||||||
authToken: ${{ secrets.CACHIX_AUTH_TOKEN }}
|
|
||||||
- name: Build
|
|
||||||
run: nix build .#packages.x86_64-darwin.default --print-build-logs
|
|
||||||
x86_64-darwin---release-package:
|
|
||||||
name: Build x86_64-darwin.release-package
|
|
||||||
runs-on:
|
|
||||||
- macos-13
|
|
||||||
needs:
|
|
||||||
- x86_64-darwin---rosenpass
|
|
||||||
- x86_64-darwin---rp
|
|
||||||
- x86_64-darwin---rosenpass-oci-image
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v4
|
|
||||||
- uses: cachix/install-nix-action@v30
|
|
||||||
with:
|
|
||||||
nix_path: nixpkgs=channel:nixos-unstable
|
|
||||||
- uses: cachix/cachix-action@v15
|
|
||||||
with:
|
|
||||||
name: rosenpass
|
|
||||||
authToken: ${{ secrets.CACHIX_AUTH_TOKEN }}
|
|
||||||
- name: Build
|
|
||||||
run: nix build .#packages.x86_64-darwin.release-package --print-build-logs
|
|
||||||
x86_64-darwin---rosenpass:
|
|
||||||
name: Build x86_64-darwin.rosenpass
|
|
||||||
runs-on:
|
|
||||||
- macos-13
|
|
||||||
needs: []
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v4
|
|
||||||
- uses: cachix/install-nix-action@v30
|
|
||||||
with:
|
|
||||||
nix_path: nixpkgs=channel:nixos-unstable
|
|
||||||
- uses: cachix/cachix-action@v15
|
|
||||||
with:
|
|
||||||
name: rosenpass
|
|
||||||
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@v4
|
|
||||||
- uses: cachix/install-nix-action@v30
|
|
||||||
with:
|
|
||||||
nix_path: nixpkgs=channel:nixos-unstable
|
|
||||||
- uses: cachix/cachix-action@v15
|
|
||||||
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:
|
|
||||||
- macos-13
|
|
||||||
needs:
|
|
||||||
- x86_64-darwin---rosenpass
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v4
|
|
||||||
- uses: cachix/install-nix-action@v30
|
|
||||||
with:
|
|
||||||
nix_path: nixpkgs=channel:nixos-unstable
|
|
||||||
- uses: cachix/cachix-action@v15
|
|
||||||
with:
|
|
||||||
name: rosenpass
|
|
||||||
authToken: ${{ secrets.CACHIX_AUTH_TOKEN }}
|
|
||||||
- name: Build
|
|
||||||
run: nix build .#packages.x86_64-darwin.rosenpass-oci-image --print-build-logs
|
|
||||||
x86_64-darwin---check:
|
|
||||||
name: Run Nix checks on x86_64-darwin
|
|
||||||
runs-on:
|
|
||||||
- macos-13
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v4
|
|
||||||
- uses: cachix/install-nix-action@v30
|
|
||||||
with:
|
|
||||||
nix_path: nixpkgs=channel:nixos-unstable
|
|
||||||
- uses: cachix/cachix-action@v15
|
|
||||||
with:
|
|
||||||
name: rosenpass
|
|
||||||
authToken: ${{ secrets.CACHIX_AUTH_TOKEN }}
|
|
||||||
- name: Check
|
|
||||||
run: nix flake check . --print-build-logs
|
|
||||||
x86_64-linux---default:
|
|
||||||
name: Build x86_64-linux.default
|
|
||||||
runs-on:
|
|
||||||
- ubuntu-latest
|
|
||||||
needs:
|
|
||||||
- x86_64-linux---rosenpass
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v4
|
|
||||||
- uses: cachix/install-nix-action@v30
|
|
||||||
with:
|
|
||||||
nix_path: nixpkgs=channel:nixos-unstable
|
|
||||||
- uses: cachix/cachix-action@v15
|
|
||||||
with:
|
|
||||||
name: rosenpass
|
|
||||||
authToken: ${{ secrets.CACHIX_AUTH_TOKEN }}
|
|
||||||
- name: Build
|
|
||||||
run: nix build .#packages.x86_64-linux.default --print-build-logs
|
|
||||||
x86_64-linux---proof-proverif:
|
|
||||||
name: Build x86_64-linux.proof-proverif
|
|
||||||
runs-on:
|
|
||||||
- ubuntu-latest
|
|
||||||
needs:
|
|
||||||
- x86_64-linux---proverif-patched
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v4
|
|
||||||
- uses: cachix/install-nix-action@v30
|
|
||||||
with:
|
|
||||||
nix_path: nixpkgs=channel:nixos-unstable
|
|
||||||
- uses: cachix/cachix-action@v15
|
|
||||||
with:
|
|
||||||
name: rosenpass
|
|
||||||
authToken: ${{ secrets.CACHIX_AUTH_TOKEN }}
|
|
||||||
- name: Build
|
|
||||||
run: nix build .#packages.x86_64-linux.proof-proverif --print-build-logs
|
|
||||||
x86_64-linux---proverif-patched:
|
|
||||||
name: Build x86_64-linux.proverif-patched
|
|
||||||
runs-on:
|
|
||||||
- ubuntu-latest
|
|
||||||
needs: []
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v4
|
|
||||||
- uses: cachix/install-nix-action@v30
|
|
||||||
with:
|
|
||||||
nix_path: nixpkgs=channel:nixos-unstable
|
|
||||||
- uses: cachix/cachix-action@v15
|
|
||||||
with:
|
|
||||||
name: rosenpass
|
|
||||||
authToken: ${{ secrets.CACHIX_AUTH_TOKEN }}
|
|
||||||
- name: Build
|
|
||||||
run: nix build .#packages.x86_64-linux.proverif-patched --print-build-logs
|
|
||||||
x86_64-linux---release-package:
|
|
||||||
name: Build x86_64-linux.release-package
|
|
||||||
runs-on:
|
|
||||||
- ubuntu-latest
|
|
||||||
needs:
|
|
||||||
- x86_64-linux---rosenpass-static
|
|
||||||
- x86_64-linux---rosenpass-static-oci-image
|
|
||||||
- x86_64-linux---rp-static
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v4
|
|
||||||
- uses: cachix/install-nix-action@v30
|
|
||||||
with:
|
|
||||||
nix_path: nixpkgs=channel:nixos-unstable
|
|
||||||
- uses: cachix/cachix-action@v15
|
|
||||||
with:
|
|
||||||
name: rosenpass
|
|
||||||
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@v4
|
|
||||||
# - uses: cachix/install-nix-action@v30
|
|
||||||
# with:
|
|
||||||
# nix_path: nixpkgs=channel:nixos-unstable
|
|
||||||
# extra_nix_config: |
|
|
||||||
# system = aarch64-linux
|
|
||||||
# - uses: cachix/cachix-action@v15
|
|
||||||
# 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:
|
|
||||||
- ubuntu-latest
|
|
||||||
needs: []
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v4
|
|
||||||
- uses: cachix/install-nix-action@v30
|
|
||||||
with:
|
|
||||||
nix_path: nixpkgs=channel:nixos-unstable
|
|
||||||
- uses: cachix/cachix-action@v15
|
|
||||||
with:
|
|
||||||
name: rosenpass
|
|
||||||
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@v4
|
|
||||||
- uses: cachix/install-nix-action@v30
|
|
||||||
with:
|
|
||||||
nix_path: nixpkgs=channel:nixos-unstable
|
|
||||||
extra_nix_config: |
|
|
||||||
system = aarch64-linux
|
|
||||||
- uses: cachix/cachix-action@v15
|
|
||||||
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@v4
|
|
||||||
- uses: cachix/install-nix-action@v30
|
|
||||||
with:
|
|
||||||
nix_path: nixpkgs=channel:nixos-unstable
|
|
||||||
extra_nix_config: |
|
|
||||||
system = aarch64-linux
|
|
||||||
- uses: cachix/cachix-action@v15
|
|
||||||
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:
|
|
||||||
- ubuntu-latest
|
|
||||||
needs:
|
|
||||||
- x86_64-linux---rosenpass
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v4
|
|
||||||
- uses: cachix/install-nix-action@v30
|
|
||||||
with:
|
|
||||||
nix_path: nixpkgs=channel:nixos-unstable
|
|
||||||
- uses: cachix/cachix-action@v15
|
|
||||||
with:
|
|
||||||
name: rosenpass
|
|
||||||
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@v4
|
|
||||||
- uses: cachix/install-nix-action@v30
|
|
||||||
with:
|
|
||||||
nix_path: nixpkgs=channel:nixos-unstable
|
|
||||||
extra_nix_config: |
|
|
||||||
system = aarch64-linux
|
|
||||||
- uses: cachix/cachix-action@v15
|
|
||||||
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:
|
|
||||||
- ubuntu-latest
|
|
||||||
needs: []
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v4
|
|
||||||
- uses: cachix/install-nix-action@v30
|
|
||||||
with:
|
|
||||||
nix_path: nixpkgs=channel:nixos-unstable
|
|
||||||
- uses: cachix/cachix-action@v15
|
|
||||||
with:
|
|
||||||
name: rosenpass
|
|
||||||
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@v4
|
|
||||||
- uses: cachix/install-nix-action@v30
|
|
||||||
with:
|
|
||||||
nix_path: nixpkgs=channel:nixos-unstable
|
|
||||||
- uses: cachix/cachix-action@v15
|
|
||||||
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:
|
|
||||||
- ubuntu-latest
|
|
||||||
needs:
|
|
||||||
- x86_64-linux---rosenpass-static
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v4
|
|
||||||
- uses: cachix/install-nix-action@v30
|
|
||||||
with:
|
|
||||||
nix_path: nixpkgs=channel:nixos-unstable
|
|
||||||
- uses: cachix/cachix-action@v15
|
|
||||||
with:
|
|
||||||
name: rosenpass
|
|
||||||
authToken: ${{ secrets.CACHIX_AUTH_TOKEN }}
|
|
||||||
- name: Build
|
|
||||||
run: nix build .#packages.x86_64-linux.rosenpass-static-oci-image --print-build-logs
|
|
||||||
x86_64-linux---whitepaper:
|
|
||||||
name: Build x86_64-linux.whitepaper
|
|
||||||
runs-on:
|
|
||||||
- ubuntu-latest
|
|
||||||
needs: []
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v4
|
|
||||||
- uses: cachix/install-nix-action@v30
|
|
||||||
with:
|
|
||||||
nix_path: nixpkgs=channel:nixos-unstable
|
|
||||||
- uses: cachix/cachix-action@v15
|
|
||||||
with:
|
|
||||||
name: rosenpass
|
|
||||||
authToken: ${{ secrets.CACHIX_AUTH_TOKEN }}
|
|
||||||
- name: Build
|
|
||||||
run: nix build .#packages.x86_64-linux.whitepaper --print-build-logs
|
|
||||||
x86_64-linux---check:
|
|
||||||
name: Run Nix checks on x86_64-linux
|
|
||||||
runs-on:
|
|
||||||
- ubuntu-latest
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v4
|
|
||||||
- uses: cachix/install-nix-action@v30
|
|
||||||
with:
|
|
||||||
nix_path: nixpkgs=channel:nixos-unstable
|
|
||||||
- uses: cachix/cachix-action@v15
|
|
||||||
with:
|
|
||||||
name: rosenpass
|
|
||||||
authToken: ${{ secrets.CACHIX_AUTH_TOKEN }}
|
|
||||||
- name: Check
|
|
||||||
run: nix flake check . --print-build-logs
|
|
||||||
x86_64-linux---whitepaper-upload:
|
|
||||||
name: Upload whitepaper x86_64-linux
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
if: ${{ github.ref == 'refs/heads/main' }}
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v4
|
|
||||||
- uses: cachix/install-nix-action@v30
|
|
||||||
with:
|
|
||||||
nix_path: nixpkgs=channel:nixos-unstable
|
|
||||||
- uses: cachix/cachix-action@v15
|
|
||||||
with:
|
|
||||||
name: rosenpass
|
|
||||||
authToken: ${{ secrets.CACHIX_AUTH_TOKEN }}
|
|
||||||
- name: Git add git sha and commit
|
|
||||||
run: cd papers && ./tex/gitinfo2.sh && git add gitHeadInfo.gin
|
|
||||||
- name: Build
|
|
||||||
run: nix build .#packages.x86_64-linux.whitepaper --print-build-logs
|
|
||||||
- name: Deploy PDF artifacts
|
- name: Deploy PDF artifacts
|
||||||
uses: peaceiris/actions-gh-pages@v4
|
if: ${{ matrix.derivation == 'whitepaper' && github.ref == 'refs/heads/main' }}
|
||||||
|
uses: peaceiris/actions-gh-pages@v3
|
||||||
with:
|
with:
|
||||||
github_token: ${{ secrets.GITHUB_TOKEN }}
|
github_token: ${{ secrets.GITHUB_TOKEN }}
|
||||||
publish_dir: result/
|
publish_dir: ${{ matrix.derivation }}-${{ matrix.nix-system }}
|
||||||
publish_branch: papers-pdf
|
publish_branch: papers-pdf
|
||||||
force_orphan: true
|
force_orphan: true
|
||||||
|
checks:
|
||||||
|
name: Run Nix checks
|
||||||
|
runs-on: nixos
|
||||||
|
needs: build
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v3
|
||||||
|
- name: Run Checks
|
||||||
|
run: nix flake check . --print-build-logs
|
||||||
|
|||||||
187
.github/workflows/qc.yaml
vendored
@@ -1,13 +1,9 @@
|
|||||||
name: QC
|
name: Quality Control
|
||||||
on:
|
on:
|
||||||
pull_request:
|
pull_request:
|
||||||
push:
|
push:
|
||||||
branches: [main]
|
branches: [main]
|
||||||
|
|
||||||
concurrency:
|
|
||||||
group: ${{ github.workflow }}-${{ github.ref }}
|
|
||||||
cancel-in-progress: true
|
|
||||||
|
|
||||||
permissions:
|
permissions:
|
||||||
checks: write
|
checks: write
|
||||||
contents: read
|
contents: read
|
||||||
@@ -16,68 +12,16 @@ jobs:
|
|||||||
prettier:
|
prettier:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v2
|
||||||
- uses: actionsx/prettier@v3
|
- uses: actionsx/prettier@v2
|
||||||
with:
|
with:
|
||||||
args: --check .
|
args: --check .
|
||||||
|
|
||||||
shellcheck:
|
|
||||||
name: Shellcheck
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v4
|
|
||||||
- name: Run ShellCheck
|
|
||||||
uses: ludeeus/action-shellcheck@master
|
|
||||||
|
|
||||||
rustfmt:
|
|
||||||
name: Rust Format
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v4
|
|
||||||
- name: Run Rust Formatting Script
|
|
||||||
run: bash format_rust_code.sh --mode check
|
|
||||||
|
|
||||||
cargo-bench:
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v4
|
|
||||||
- uses: actions/cache@v4
|
|
||||||
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@v4
|
|
||||||
- name: Check rp.1
|
|
||||||
run: doc/check.sh doc/rp.1
|
|
||||||
|
|
||||||
cargo-audit:
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v4
|
|
||||||
- uses: actions-rs/audit-check@v1
|
|
||||||
with:
|
|
||||||
token: ${{ secrets.GITHUB_TOKEN }}
|
|
||||||
|
|
||||||
cargo-clippy:
|
cargo-clippy:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v2
|
||||||
- uses: actions/cache@v4
|
- uses: actions/cache@v3
|
||||||
with:
|
with:
|
||||||
path: |
|
path: |
|
||||||
~/.cargo/bin/
|
~/.cargo/bin/
|
||||||
@@ -87,126 +31,17 @@ jobs:
|
|||||||
target/
|
target/
|
||||||
key: ${{ runner.os }}-cargo-${{ hashFiles('**/Cargo.lock') }}
|
key: ${{ runner.os }}-cargo-${{ hashFiles('**/Cargo.lock') }}
|
||||||
- run: rustup component add clippy
|
- run: rustup component add clippy
|
||||||
|
- name: Install xmllint
|
||||||
|
run: sudo apt-get install -y libsodium-dev
|
||||||
- uses: actions-rs/clippy-check@v1
|
- uses: actions-rs/clippy-check@v1
|
||||||
with:
|
with:
|
||||||
token: ${{ secrets.GITHUB_TOKEN }}
|
token: ${{ secrets.GITHUB_TOKEN }}
|
||||||
args: --all-features
|
args: --all-features
|
||||||
|
|
||||||
cargo-doc:
|
cargo-audit:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v1
|
||||||
- uses: actions/cache@v4
|
- uses: actions-rs/audit-check@v1
|
||||||
with:
|
with:
|
||||||
path: |
|
token: ${{ secrets.GITHUB_TOKEN }}
|
||||||
~/.cargo/bin/
|
|
||||||
~/.cargo/registry/index/
|
|
||||||
~/.cargo/registry/cache/
|
|
||||||
~/.cargo/git/db/
|
|
||||||
target/
|
|
||||||
key: ${{ runner.os }}-cargo-${{ hashFiles('**/Cargo.lock') }}
|
|
||||||
- run: rustup component add clippy
|
|
||||||
# `--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: ${{ matrix.os }}
|
|
||||||
strategy:
|
|
||||||
matrix:
|
|
||||||
os: [ubuntu-latest, macos-13]
|
|
||||||
# - ubuntu is x86-64
|
|
||||||
# - macos-13 is also x86-64 architecture
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v4
|
|
||||||
- uses: actions/cache@v4
|
|
||||||
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 test --workspace --all-features
|
|
||||||
|
|
||||||
cargo-test-nix-devshell-x86_64-linux:
|
|
||||||
runs-on:
|
|
||||||
- ubuntu-latest
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v4
|
|
||||||
- uses: actions/cache@v4
|
|
||||||
with:
|
|
||||||
path: |
|
|
||||||
~/.cargo/bin/
|
|
||||||
~/.cargo/registry/index/
|
|
||||||
~/.cargo/registry/cache/
|
|
||||||
~/.cargo/git/db/
|
|
||||||
target/
|
|
||||||
key: ${{ runner.os }}-cargo-${{ hashFiles('**/Cargo.lock') }}
|
|
||||||
- uses: cachix/install-nix-action@v30
|
|
||||||
with:
|
|
||||||
nix_path: nixpkgs=channel:nixos-unstable
|
|
||||||
- uses: cachix/cachix-action@v15
|
|
||||||
with:
|
|
||||||
name: rosenpass
|
|
||||||
authToken: ${{ secrets.CACHIX_AUTH_TOKEN }}
|
|
||||||
- run: nix develop --command cargo test --workspace --all-features
|
|
||||||
|
|
||||||
cargo-fuzz:
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v4
|
|
||||||
- uses: actions/cache@v4
|
|
||||||
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@v4
|
|
||||||
- run: rustup default nightly
|
|
||||||
- run: rustup component add llvm-tools-preview
|
|
||||||
- run: |
|
|
||||||
cargo install cargo-llvm-cov || true
|
|
||||||
cargo install grcov || true
|
|
||||||
./coverage_report.sh
|
|
||||||
# If using tarapulin
|
|
||||||
#- run: cargo install cargo-tarpaulin
|
|
||||||
#- run: cargo tarpaulin --out Xml
|
|
||||||
- name: Upload coverage reports to Codecov
|
|
||||||
uses: codecov/codecov-action@v5
|
|
||||||
with:
|
|
||||||
files: ./target/grcov/lcov
|
|
||||||
verbose: true
|
|
||||||
env:
|
|
||||||
CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }}
|
|
||||||
|
|||||||
37
.github/workflows/regressions.yml
vendored
@@ -1,37 +0,0 @@
|
|||||||
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@v4
|
|
||||||
- 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 ]
|
|
||||||
|
|
||||||
boot-race:
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v4
|
|
||||||
- run: cargo build --bin rosenpass --release
|
|
||||||
- run: chmod +x .ci/boot_race/run.sh
|
|
||||||
- run: cargo run --release --bin rosenpass gen-keys .ci/boot_race/a.toml
|
|
||||||
- run: cargo run --release --bin rosenpass gen-keys .ci/boot_race/b.toml
|
|
||||||
- run: .ci/boot_race/run.sh 5 2 .ci/boot_race/a.toml .ci/boot_race/b.toml
|
|
||||||
- run: .ci/boot_race/run.sh 5 1 .ci/boot_race/a.toml .ci/boot_race/b.toml
|
|
||||||
- run: .ci/boot_race/run.sh 5 0 .ci/boot_race/a.toml .ci/boot_race/b.toml
|
|
||||||
77
.github/workflows/release.yaml
vendored
@@ -3,69 +3,26 @@ permissions:
|
|||||||
contents: write
|
contents: write
|
||||||
on:
|
on:
|
||||||
push:
|
push:
|
||||||
tags:
|
tags: ["v*"]
|
||||||
- v*
|
|
||||||
jobs:
|
jobs:
|
||||||
i686-linux---release:
|
release:
|
||||||
name: Build release artifacts for i686-linux
|
name: Build ${{ matrix.derivation }} on ${{ matrix.nix-system }}
|
||||||
runs-on:
|
runs-on:
|
||||||
- ubuntu-latest
|
- nix
|
||||||
|
- ${{ matrix.nix-system }}
|
||||||
|
strategy:
|
||||||
|
fail-fast: false
|
||||||
|
matrix:
|
||||||
|
nix-system:
|
||||||
|
- x86_64-linux
|
||||||
|
# - aarch64-linux
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v3
|
||||||
- uses: cachix/install-nix-action@v30
|
- name: Build release-package for ${{ matrix.nix-system }}
|
||||||
with:
|
|
||||||
nix_path: nixpkgs=channel:nixos-unstable
|
|
||||||
- uses: cachix/cachix-action@v15
|
|
||||||
with:
|
|
||||||
name: rosenpass
|
|
||||||
authToken: ${{ secrets.CACHIX_AUTH_TOKEN }}
|
|
||||||
- name: Build release
|
|
||||||
run: nix build .#release-package --print-build-logs
|
run: nix build .#release-package --print-build-logs
|
||||||
- name: Release
|
- name: Release
|
||||||
uses: softprops/action-gh-release@v2
|
uses: softprops/action-gh-release@v1
|
||||||
with:
|
with:
|
||||||
draft: ${{ contains(github.ref_name, 'rc') }}
|
files: |
|
||||||
prerelease: ${{ contains(github.ref_name, 'alpha') || contains(github.ref_name, 'beta') }}
|
result/*
|
||||||
files: result/*
|
|
||||||
x86_64-darwin---release:
|
|
||||||
name: Build release artifacts for x86_64-darwin
|
|
||||||
runs-on:
|
|
||||||
- macos-13
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v4
|
|
||||||
- uses: cachix/install-nix-action@v30
|
|
||||||
with:
|
|
||||||
nix_path: nixpkgs=channel:nixos-unstable
|
|
||||||
- uses: cachix/cachix-action@v15
|
|
||||||
with:
|
|
||||||
name: rosenpass
|
|
||||||
authToken: ${{ secrets.CACHIX_AUTH_TOKEN }}
|
|
||||||
- name: Build release
|
|
||||||
run: nix build .#release-package --print-build-logs
|
|
||||||
- name: Release
|
|
||||||
uses: softprops/action-gh-release@v2
|
|
||||||
with:
|
|
||||||
draft: ${{ contains(github.ref_name, 'rc') }}
|
|
||||||
prerelease: ${{ contains(github.ref_name, 'alpha') || contains(github.ref_name, 'beta') }}
|
|
||||||
files: result/*
|
|
||||||
x86_64-linux---release:
|
|
||||||
name: Build release artifacts for x86_64-linux
|
|
||||||
runs-on:
|
|
||||||
- ubuntu-latest
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v4
|
|
||||||
- uses: cachix/install-nix-action@v30
|
|
||||||
with:
|
|
||||||
nix_path: nixpkgs=channel:nixos-unstable
|
|
||||||
- uses: cachix/cachix-action@v15
|
|
||||||
with:
|
|
||||||
name: rosenpass
|
|
||||||
authToken: ${{ secrets.CACHIX_AUTH_TOKEN }}
|
|
||||||
- name: Build release
|
|
||||||
run: nix build .#release-package --print-build-logs
|
|
||||||
- name: Release
|
|
||||||
uses: softprops/action-gh-release@v2
|
|
||||||
with:
|
|
||||||
draft: ${{ contains(github.ref_name, 'rc') }}
|
|
||||||
prerelease: ${{ contains(github.ref_name, 'alpha') || contains(github.ref_name, 'beta') }}
|
|
||||||
files: result/*
|
|
||||||
|
|||||||
5
.gitignore
vendored
@@ -20,8 +20,3 @@ _markdown_*
|
|||||||
**/result
|
**/result
|
||||||
**/result-*
|
**/result-*
|
||||||
.direnv
|
.direnv
|
||||||
|
|
||||||
# Visual studio code
|
|
||||||
.vscode
|
|
||||||
|
|
||||||
/output
|
|
||||||
|
|||||||
@@ -1,17 +0,0 @@
|
|||||||
# TODO use CI_JOB_TOKEN once https://gitlab.com/groups/gitlab-org/-/epics/6310 is fixed
|
|
||||||
pull-from-gh:
|
|
||||||
only: ["schedules"]
|
|
||||||
variables:
|
|
||||||
REMOTE: "https://github.com/rosenpass/rosenpass.git"
|
|
||||||
LOCAL: " git@gitlab.com:rosenpass/rosenpass.git"
|
|
||||||
GIT_STRATEGY: none
|
|
||||||
before_script:
|
|
||||||
- mkdir ~/.ssh/
|
|
||||||
- echo "$SSH_KNOWN_HOSTS" > ~/.ssh/known_hosts
|
|
||||||
- echo "$REPO_SSH_KEY" > ~/.ssh/id_ed25519
|
|
||||||
- chmod 600 --recursive ~/.ssh/
|
|
||||||
- git config --global user.email "ci@gitlab.com"
|
|
||||||
- git config --global user.name "CI"
|
|
||||||
script:
|
|
||||||
- git clone --mirror $REMOTE rosenpass
|
|
||||||
- cd rosenpass && git push --mirror $LOCAL
|
|
||||||
@@ -1,5 +1,4 @@
|
|||||||
.direnv/
|
.direnv/
|
||||||
flake.lock
|
|
||||||
papers/whitepaper.md
|
papers/whitepaper.md
|
||||||
src/usage.md
|
|
||||||
target/
|
target/
|
||||||
|
src/usage.md
|
||||||
|
|||||||
@@ -1,41 +0,0 @@
|
|||||||
# Contributing to Rosenpass
|
|
||||||
|
|
||||||
## Common operations
|
|
||||||
|
|
||||||
### Apply code formatting
|
|
||||||
|
|
||||||
Format rust code:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
cargo fmt
|
|
||||||
```
|
|
||||||
|
|
||||||
Format rust code in markdown files:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
./format_rust_code.sh --mode fix
|
|
||||||
```
|
|
||||||
|
|
||||||
### Spawn a development environment with nix
|
|
||||||
|
|
||||||
```bash
|
|
||||||
nix develop .#fullEnv
|
|
||||||
```
|
|
||||||
|
|
||||||
You need to [install this nix package manager](https://wiki.archlinux.org/title/Nix) first.
|
|
||||||
|
|
||||||
### Run our test
|
|
||||||
|
|
||||||
Make sure to increase the stack size available; some of our cryptography operations require a lot of stack memory.
|
|
||||||
|
|
||||||
```bash
|
|
||||||
RUST_MIN_STACK=8388608 cargo test --workspace --all-features
|
|
||||||
```
|
|
||||||
|
|
||||||
### Generate coverage reports
|
|
||||||
|
|
||||||
Keep in mind that many of Rosenpass' tests are doctests, so to get an accurate read on our code coverage, you have to include doctests:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
./coverage_report.sh
|
|
||||||
```
|
|
||||||
2586
Cargo.lock
generated
116
Cargo.toml
@@ -1,93 +1,35 @@
|
|||||||
[workspace]
|
[package]
|
||||||
resolver = "2"
|
name = "rosenpass"
|
||||||
|
version = "0.1.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"
|
||||||
|
|
||||||
members = [
|
[[bench]]
|
||||||
"rosenpass",
|
name = "handshake"
|
||||||
"cipher-traits",
|
harness = false
|
||||||
"ciphers",
|
|
||||||
"util",
|
|
||||||
"constant-time",
|
|
||||||
"oqs",
|
|
||||||
"to",
|
|
||||||
"fuzz",
|
|
||||||
"secret-memory",
|
|
||||||
"rp",
|
|
||||||
"wireguard-broker",
|
|
||||||
]
|
|
||||||
|
|
||||||
default-members = ["rosenpass", "rp", "wireguard-broker"]
|
[dependencies]
|
||||||
|
anyhow = { version = "1.0.52", features = ["backtrace"] }
|
||||||
[workspace.metadata.release]
|
base64 = "0.13.0"
|
||||||
# ensure that adding `--package` as argument to `cargo release` still creates version tags in the form of `vx.y.z`
|
clap = { version = "3.0.0", features = ["yaml"] }
|
||||||
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.69"
|
|
||||||
paste = "1.0.15"
|
|
||||||
env_logger = "0.10.2"
|
|
||||||
toml = "0.7.8"
|
|
||||||
static_assertions = "1.1.0"
|
static_assertions = "1.1.0"
|
||||||
allocator-api2 = "0.2.14"
|
memoffset = "0.6.5"
|
||||||
memsec = { git = "https://github.com/rosenpass/memsec.git", rev = "aceb9baee8aec6844125bd6612f92e9a281373df", features = [
|
libsodium-sys-stable = { version = "1.19.26", features = ["use-pkg-config"] }
|
||||||
"alloc_ext",
|
oqs-sys = { version = "0.7.1", default-features = false, features = ['classic_mceliece', 'kyber'] }
|
||||||
] }
|
lazy_static = "1.4.0"
|
||||||
rand = "0.8.5"
|
thiserror = "1.0.38"
|
||||||
typenum = "1.17.0"
|
paste = "1.0.11"
|
||||||
log = { version = "0.4.22" }
|
log = { version = "0.4.17", optional = true }
|
||||||
clap = { version = "4.5.23", features = ["derive"] }
|
env_logger = { version = "0.10.0", optional = true }
|
||||||
clap_mangen = "0.2.24"
|
|
||||||
clap_complete = "4.5.38"
|
|
||||||
serde = { version = "1.0.215", features = ["derive"] }
|
|
||||||
arbitrary = { version = "1.4.1", features = ["derive"] }
|
|
||||||
anyhow = { version = "1.0.94", features = ["backtrace", "std"] }
|
|
||||||
mio = { version = "1.0.3", 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.42", features = ["macros", "rt-multi-thread"] }
|
|
||||||
postcard = { version = "1.1.1", 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" }
|
|
||||||
signal-hook = "0.3.17"
|
|
||||||
|
|
||||||
#Dev dependencies
|
[dev-dependencies]
|
||||||
serial_test = "3.2.0"
|
criterion = "0.3.5"
|
||||||
tempfile = "3"
|
|
||||||
stacker = "0.1.17"
|
|
||||||
libfuzzer-sys = "0.4"
|
|
||||||
test_bin = "0.4.0"
|
test_bin = "0.4.0"
|
||||||
criterion = "0.4.0"
|
|
||||||
allocator-api2-tests = "0.2.15"
|
|
||||||
procspawn = { version = "1.0.1", features = ["test-support"] }
|
|
||||||
|
|
||||||
|
[features]
|
||||||
#Broker dependencies (might need cleanup or changes)
|
default = ["log", "env_logger"]
|
||||||
wireguard-uapi = { version = "3.0.0", features = ["xplatform"] }
|
|
||||||
command-fds = "0.2.3"
|
|
||||||
rustix = { version = "0.38.41", features = ["net", "fs", "process"] }
|
|
||||||
|
|||||||
@@ -1,25 +0,0 @@
|
|||||||
#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].
|
|
||||||
@@ -1,96 +0,0 @@
|
|||||||
#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].
|
|
||||||
@@ -1,29 +0,0 @@
|
|||||||
#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.
|
|
||||||
@@ -1,136 +0,0 @@
|
|||||||
#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)).
|
|
||||||
|
|
||||||
@@ -1,155 +0,0 @@
|
|||||||
/*
|
|
||||||
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
|
|
||||||
@@ -1,36 +0,0 @@
|
|||||||
|
|
||||||
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).)
|
|
||||||
@@ -1,18 +1,17 @@
|
|||||||
use anyhow::Result;
|
use anyhow::Result;
|
||||||
use rosenpass::protocol::{CryptoServer, HandleMsgResult, MsgBuf, PeerPtr, SPk, SSk, SymKey};
|
use rosenpass::{
|
||||||
use std::ops::DerefMut;
|
pqkem::{CCAKEM, KEM},
|
||||||
|
protocol::{CcaPk, CcaSk, HandleMsgResult, MsgBuf, PeerPtr, Server, SymKey},
|
||||||
use rosenpass_cipher_traits::Kem;
|
sodium::sodium_init,
|
||||||
use rosenpass_ciphers::kem::StaticKem;
|
};
|
||||||
|
|
||||||
use criterion::{black_box, criterion_group, criterion_main, Criterion};
|
use criterion::{black_box, criterion_group, criterion_main, Criterion};
|
||||||
use rosenpass_secret_memory::secret_policy_try_use_memfd_secrets;
|
|
||||||
|
|
||||||
fn handle(
|
fn handle(
|
||||||
tx: &mut CryptoServer,
|
tx: &mut Server,
|
||||||
msgb: &mut MsgBuf,
|
msgb: &mut MsgBuf,
|
||||||
msgl: usize,
|
msgl: usize,
|
||||||
rx: &mut CryptoServer,
|
rx: &mut Server,
|
||||||
resb: &mut MsgBuf,
|
resb: &mut MsgBuf,
|
||||||
) -> Result<(Option<SymKey>, Option<SymKey>)> {
|
) -> Result<(Option<SymKey>, Option<SymKey>)> {
|
||||||
let HandleMsgResult {
|
let HandleMsgResult {
|
||||||
@@ -31,7 +30,7 @@ fn handle(
|
|||||||
Ok((txk, rxk.or(xch)))
|
Ok((txk, rxk.or(xch)))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn hs(ini: &mut CryptoServer, res: &mut CryptoServer) -> Result<()> {
|
fn hs(ini: &mut Server, res: &mut Server) -> Result<()> {
|
||||||
let (mut inib, mut resb) = (MsgBuf::zero(), MsgBuf::zero());
|
let (mut inib, mut resb) = (MsgBuf::zero(), MsgBuf::zero());
|
||||||
let sz = ini.initiate_handshake(PeerPtr(0), &mut *inib)?;
|
let sz = ini.initiate_handshake(PeerPtr(0), &mut *inib)?;
|
||||||
let (kini, kres) = handle(ini, &mut inib, sz, res, &mut resb)?;
|
let (kini, kres) = handle(ini, &mut inib, sz, res, &mut resb)?;
|
||||||
@@ -39,35 +38,32 @@ fn hs(ini: &mut CryptoServer, res: &mut CryptoServer) -> Result<()> {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn keygen() -> Result<(SSk, SPk)> {
|
fn keygen() -> Result<(CcaSk, CcaPk)> {
|
||||||
let (mut sk, mut pk) = (SSk::zero(), SPk::zero());
|
let (mut sk, mut pk) = (CcaSk::zero(), CcaPk::zero());
|
||||||
StaticKem::keygen(sk.secret_mut(), pk.deref_mut())?;
|
CCAKEM::keygen(sk.secret_mut(), pk.secret_mut())?;
|
||||||
Ok((sk, pk))
|
Ok((sk, pk))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn make_server_pair() -> Result<(CryptoServer, CryptoServer)> {
|
fn make_server_pair() -> Result<(Server, Server)> {
|
||||||
let psk = SymKey::random();
|
let psk = SymKey::random();
|
||||||
let ((ska, pka), (skb, pkb)) = (keygen()?, keygen()?);
|
let ((ska, pka), (skb, pkb)) = (keygen()?, keygen()?);
|
||||||
let (mut a, mut b) = (
|
let (mut a, mut b) = (Server::new(ska, pka.clone()), Server::new(skb, pkb.clone()));
|
||||||
CryptoServer::new(ska, pka.clone()),
|
|
||||||
CryptoServer::new(skb, pkb.clone()),
|
|
||||||
);
|
|
||||||
a.add_peer(Some(psk.clone()), pkb)?;
|
a.add_peer(Some(psk.clone()), pkb)?;
|
||||||
b.add_peer(Some(psk), pka)?;
|
b.add_peer(Some(psk), pka)?;
|
||||||
Ok((a, b))
|
Ok((a, b))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn criterion_benchmark(c: &mut Criterion) {
|
fn criterion_benchmark(c: &mut Criterion) {
|
||||||
secret_policy_try_use_memfd_secrets();
|
sodium_init().unwrap();
|
||||||
let (mut a, mut b) = make_server_pair().unwrap();
|
let (mut a, mut b) = make_server_pair().unwrap();
|
||||||
c.bench_function("cca_secret_alloc", |bench| {
|
c.bench_function("cca_secret_alloc", |bench| {
|
||||||
bench.iter(|| {
|
bench.iter(|| {
|
||||||
SSk::zero();
|
CcaSk::zero();
|
||||||
})
|
})
|
||||||
});
|
});
|
||||||
c.bench_function("cca_public_alloc", |bench| {
|
c.bench_function("cca_public_alloc", |bench| {
|
||||||
bench.iter(|| {
|
bench.iter(|| {
|
||||||
SPk::zero();
|
CcaPk::zero();
|
||||||
})
|
})
|
||||||
});
|
});
|
||||||
c.bench_function("keygen", |bench| {
|
c.bench_function("keygen", |bench| {
|
||||||
@@ -1,12 +0,0 @@
|
|||||||
[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]
|
|
||||||
@@ -1,5 +0,0 @@
|
|||||||
# 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.
|
|
||||||
@@ -1,45 +0,0 @@
|
|||||||
//! 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>;
|
|
||||||
}
|
|
||||||
@@ -1,2 +0,0 @@
|
|||||||
mod kem;
|
|
||||||
pub use kem::Kem;
|
|
||||||
@@ -1,26 +0,0 @@
|
|||||||
[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 }
|
|
||||||
@@ -1,5 +0,0 @@
|
|||||||
# 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.
|
|
||||||
@@ -1,206 +0,0 @@
|
|||||||
use anyhow::Result;
|
|
||||||
use rosenpass_secret_memory::Secret;
|
|
||||||
use rosenpass_to::To;
|
|
||||||
|
|
||||||
use crate::keyed_hash as hash;
|
|
||||||
|
|
||||||
pub use hash::KEY_LEN;
|
|
||||||
|
|
||||||
///
|
|
||||||
///```rust
|
|
||||||
/// # use rosenpass_ciphers::hash_domain::{HashDomain, HashDomainNamespace, SecretHashDomain, SecretHashDomainNamespace};
|
|
||||||
/// use rosenpass_secret_memory::Secret;
|
|
||||||
/// # rosenpass_secret_memory::secret_policy_use_only_malloc_secrets();
|
|
||||||
///
|
|
||||||
/// const PROTOCOL_IDENTIFIER: &str = "MY_PROTOCOL:IDENTIFIER";
|
|
||||||
/// # fn do_doc_test() -> Result<(), Box<dyn std::error::Error>> {
|
|
||||||
/// // create use once hash domain for the protocol identifier
|
|
||||||
/// let mut hash_domain = HashDomain::zero();
|
|
||||||
/// hash_domain = hash_domain.mix(PROTOCOL_IDENTIFIER.as_bytes())?;
|
|
||||||
/// // upgrade to reusable hash domain
|
|
||||||
/// let hash_domain_namespace: HashDomainNamespace = hash_domain.dup();
|
|
||||||
/// // derive new key
|
|
||||||
/// let key_identifier = "my_key_identifier";
|
|
||||||
/// let key = hash_domain_namespace.mix(key_identifier.as_bytes())?.into_value();
|
|
||||||
/// // derive a new key based on a secret
|
|
||||||
/// const MY_SECRET_LEN: usize = 21;
|
|
||||||
/// let my_secret_bytes = "my super duper secret".as_bytes();
|
|
||||||
/// let my_secret: Secret<21> = Secret::from_slice("my super duper secret".as_bytes());
|
|
||||||
/// let secret_hash_domain: SecretHashDomain = hash_domain_namespace.mix_secret(my_secret)?;
|
|
||||||
/// // derive a new key based on the secret key
|
|
||||||
/// let new_key_identifier = "my_new_key_identifier".as_bytes();
|
|
||||||
/// let new_key = secret_hash_domain.mix(new_key_identifier)?.into_secret();
|
|
||||||
///
|
|
||||||
/// # Ok(())
|
|
||||||
/// # }
|
|
||||||
/// # do_doc_test().unwrap();
|
|
||||||
///
|
|
||||||
///```
|
|
||||||
///
|
|
||||||
|
|
||||||
// TODO Use a proper Dec interface
|
|
||||||
/// A use-once hash domain for a specified key that can be used directly.
|
|
||||||
/// The key must consist of [KEY_LEN] many bytes. If the key must remain secret,
|
|
||||||
/// use [SecretHashDomain] instead.
|
|
||||||
#[derive(Clone, Debug)]
|
|
||||||
pub struct HashDomain([u8; KEY_LEN]);
|
|
||||||
/// A reusable hash domain for a namespace identified by the key.
|
|
||||||
/// The key must consist of [KEY_LEN] many bytes. If the key must remain secret,
|
|
||||||
/// use [SecretHashDomainNamespace] instead.
|
|
||||||
#[derive(Clone, Debug)]
|
|
||||||
pub struct HashDomainNamespace([u8; KEY_LEN]);
|
|
||||||
/// A use-once hash domain for a specified key that can be used directly
|
|
||||||
/// by wrapping it in [Secret]. The key must consist of [KEY_LEN] many bytes.
|
|
||||||
#[derive(Clone, Debug)]
|
|
||||||
pub struct SecretHashDomain(Secret<KEY_LEN>);
|
|
||||||
/// A reusable secure hash domain for a namespace identified by the key and that keeps the key secure
|
|
||||||
/// by wrapping it in [Secret]. The key must consist of [KEY_LEN] many bytes.
|
|
||||||
#[derive(Clone, Debug)]
|
|
||||||
pub struct SecretHashDomainNamespace(Secret<KEY_LEN>);
|
|
||||||
|
|
||||||
impl HashDomain {
|
|
||||||
/// Creates a nw [HashDomain] initialized with a all-zeros key.
|
|
||||||
pub fn zero() -> Self {
|
|
||||||
Self([0u8; KEY_LEN])
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Turns this [HashDomain] into a [HashDomainNamespace], keeping the key.
|
|
||||||
pub fn dup(self) -> HashDomainNamespace {
|
|
||||||
HashDomainNamespace(self.0)
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Turns this [HashDomain] into a [SecretHashDomain] by wrapping the key into a [Secret]
|
|
||||||
/// and creating a new [SecretHashDomain] from it.
|
|
||||||
pub fn turn_secret(self) -> SecretHashDomain {
|
|
||||||
SecretHashDomain(Secret::from_slice(&self.0))
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO: Protocol! Use domain separation to ensure that
|
|
||||||
/// Creates a new [HashDomain] by mixing in a new key `v`. Specifically,
|
|
||||||
/// it evaluates [hash::hash] with this HashDomain's key as the key and `v`
|
|
||||||
/// as the `data` and uses the result as the key for the new [HashDomain].
|
|
||||||
///
|
|
||||||
pub fn mix(self, v: &[u8]) -> Result<Self> {
|
|
||||||
Ok(Self(hash::hash(&self.0, v).collect::<[u8; KEY_LEN]>()?))
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Creates a new [SecretHashDomain] by mixing in a new key `v`
|
|
||||||
/// by calling [SecretHashDomain::invoke_primitive] with this
|
|
||||||
/// [HashDomain]'s key as `k` and `v` as `d`.
|
|
||||||
pub fn mix_secret<const N: usize>(self, v: Secret<N>) -> Result<SecretHashDomain> {
|
|
||||||
SecretHashDomain::invoke_primitive(&self.0, v.secret())
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Gets the key of this [HashDomain].
|
|
||||||
pub fn into_value(self) -> [u8; KEY_LEN] {
|
|
||||||
self.0
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl HashDomainNamespace {
|
|
||||||
/// Creates a new [HashDomain] by mixing in a new key `v`. Specifically,
|
|
||||||
/// it evaluates [hash::hash] with the key of this HashDomainNamespace key as the key and `v`
|
|
||||||
/// as the `data` and uses the result as the key for the new [HashDomain].
|
|
||||||
pub fn mix(&self, v: &[u8]) -> Result<HashDomain> {
|
|
||||||
Ok(HashDomain(
|
|
||||||
hash::hash(&self.0, v).collect::<[u8; KEY_LEN]>()?,
|
|
||||||
))
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Creates a new [SecretHashDomain] by mixing in a new key `v`
|
|
||||||
/// by calling [SecretHashDomain::invoke_primitive] with the key of this
|
|
||||||
/// [HashDomainNamespace] as `k` and `v` as `d`.
|
|
||||||
///
|
|
||||||
/// It requires that `v` consists of exactly [KEY_LEN] many bytes.
|
|
||||||
pub fn mix_secret<const N: usize>(&self, v: Secret<N>) -> Result<SecretHashDomain> {
|
|
||||||
SecretHashDomain::invoke_primitive(&self.0, v.secret())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl SecretHashDomain {
|
|
||||||
/// Create a new [SecretHashDomain] with the given key `k` and data `d` by calling
|
|
||||||
/// [hash::hash] with `k` as the `key` and `d` s the `data`, and using the result
|
|
||||||
/// as the content for the new [SecretHashDomain].
|
|
||||||
/// Both `k` and `d` have to be exactly [KEY_LEN] bytes in length.
|
|
||||||
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)
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Creates a new [SecretHashDomain] that is initialized with an all zeros key.
|
|
||||||
pub fn zero() -> Self {
|
|
||||||
Self(Secret::zero())
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Turns this [SecretHashDomain] into a [SecretHashDomainNamespace].
|
|
||||||
pub fn dup(self) -> SecretHashDomainNamespace {
|
|
||||||
SecretHashDomainNamespace(self.0)
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Creates a new [SecretHashDomain] from a [Secret] `k`.
|
|
||||||
///
|
|
||||||
/// It requires that `k` consist of exactly [KEY_LEN] bytes.
|
|
||||||
pub fn danger_from_secret(k: Secret<KEY_LEN>) -> Self {
|
|
||||||
Self(k)
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Creates a new [SecretHashDomain] by mixing in a new key `v`. Specifically,
|
|
||||||
/// it evaluates [hash::hash] with this [SecretHashDomain]'s key as the key and `v`
|
|
||||||
/// as the `data` and uses the result as the key for the new [SecretHashDomain].
|
|
||||||
///
|
|
||||||
/// It requires that `v` consists of exactly [KEY_LEN] many bytes.
|
|
||||||
pub fn mix(self, v: &[u8]) -> Result<SecretHashDomain> {
|
|
||||||
Self::invoke_primitive(self.0.secret(), v)
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Creates a new [SecretHashDomain] by mixing in a new key `v`
|
|
||||||
/// by calling [SecretHashDomain::invoke_primitive] with the key of this
|
|
||||||
/// [HashDomainNamespace] as `k` and `v` as `d`.
|
|
||||||
///
|
|
||||||
/// It requires that `v` consists of exactly [KEY_LEN] many bytes.
|
|
||||||
pub fn mix_secret<const N: usize>(self, v: Secret<N>) -> Result<SecretHashDomain> {
|
|
||||||
Self::invoke_primitive(self.0.secret(), v.secret())
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Get the secret key data from this [SecretHashDomain].
|
|
||||||
pub fn into_secret(self) -> Secret<KEY_LEN> {
|
|
||||||
self.0
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Evaluate [hash::hash] with this [SecretHashDomain]'s data as the `key` and
|
|
||||||
/// `dst` as the `data` and stores the result as the new data for this [SecretHashDomain].
|
|
||||||
///
|
|
||||||
/// It requires that both `v` and `d` consist of exactly [KEY_LEN] many bytes.
|
|
||||||
pub fn into_secret_slice(mut self, v: &[u8], dst: &[u8]) -> Result<()> {
|
|
||||||
hash::hash(v, dst).to(self.0.secret_mut())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl SecretHashDomainNamespace {
|
|
||||||
/// Creates a new [SecretHashDomain] by mixing in a new key `v`. Specifically,
|
|
||||||
/// it evaluates [hash::hash] with the key of this HashDomainNamespace key as the key and `v`
|
|
||||||
/// as the `data` and uses the result as the key for the new [HashDomain].
|
|
||||||
///
|
|
||||||
/// It requires that `v` consists of exactly [KEY_LEN] many bytes.
|
|
||||||
pub fn mix(&self, v: &[u8]) -> Result<SecretHashDomain> {
|
|
||||||
SecretHashDomain::invoke_primitive(self.0.secret(), v)
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Creates a new [SecretHashDomain] by mixing in a new key `v`
|
|
||||||
/// by calling [SecretHashDomain::invoke_primitive] with the key of this
|
|
||||||
/// [HashDomainNamespace] as `k` and `v` as `d`.
|
|
||||||
///
|
|
||||||
/// It requires that `v` consists of exactly [KEY_LEN] many bytes.
|
|
||||||
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
|
|
||||||
/// Get the secret key data from this [SecretHashDomain].
|
|
||||||
pub fn danger_into_secret(self) -> Secret<KEY_LEN> {
|
|
||||||
self.0
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,52 +0,0 @@
|
|||||||
use static_assertions::const_assert;
|
|
||||||
|
|
||||||
pub mod subtle;
|
|
||||||
|
|
||||||
/// All keyed primitives in this crate use 32 byte keys
|
|
||||||
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);
|
|
||||||
|
|
||||||
/// Keyed hashing
|
|
||||||
///
|
|
||||||
/// This should only be used for implementation details; anything with relevance
|
|
||||||
/// to the cryptographic protocol should use the facilities in [hash_domain], (though
|
|
||||||
/// hash domain uses this module internally)
|
|
||||||
pub mod keyed_hash {
|
|
||||||
pub use crate::subtle::incorrect_hmac_blake2b::{
|
|
||||||
hash, KEY_LEN, KEY_MAX, KEY_MIN, OUT_MAX, OUT_MIN,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Authenticated encryption with associated data
|
|
||||||
/// Chacha20poly1305 is used.
|
|
||||||
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
|
|
||||||
/// XChacha20poly1305 is used.
|
|
||||||
pub mod xaead {
|
|
||||||
pub use crate::subtle::xchacha20poly1305_ietf::{
|
|
||||||
decrypt, encrypt, KEY_LEN, NONCE_LEN, TAG_LEN,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
pub mod hash_domain;
|
|
||||||
|
|
||||||
/// This crate includes two key encapsulation mechanisms.
|
|
||||||
/// Namely ClassicMceliece460896 (as [StaticKem]) and Kyber512 (as [EphemeralKem]).
|
|
||||||
///
|
|
||||||
/// See [rosenpass_oqs::ClassicMceliece460896](rosenpass_oqs::ClassicMceliece460896)
|
|
||||||
/// and [rosenpass_oqs::Kyber512](rosenpass_oqs::Kyber512) for more details on the specific KEMS.
|
|
||||||
///
|
|
||||||
pub mod kem {
|
|
||||||
pub use rosenpass_oqs::ClassicMceliece460896 as StaticKem;
|
|
||||||
pub use rosenpass_oqs::Kyber512 as EphemeralKem;
|
|
||||||
}
|
|
||||||
@@ -1,65 +0,0 @@
|
|||||||
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;
|
|
||||||
|
|
||||||
/// Specify that the used implementation of BLAKE2b is the MAC version of BLAKE2b
|
|
||||||
/// with output and key length of 32 bytes (see [Blake2bMac<U32>]).
|
|
||||||
type Impl = Blake2bMac<U32>;
|
|
||||||
|
|
||||||
type KeyLen = <Impl as KeySizeUser>::KeySize;
|
|
||||||
type OutLen = <Impl as OutputSizeUser>::OutputSize;
|
|
||||||
|
|
||||||
/// The key length for BLAKE2b supported by this API. Currently 32 Bytes.
|
|
||||||
const KEY_LEN: usize = typenum2const! { KeyLen };
|
|
||||||
/// The output length for BLAKE2b supported by this API. Currently 32 Bytes.
|
|
||||||
const OUT_LEN: usize = typenum2const! { OutLen };
|
|
||||||
|
|
||||||
/// Minimal key length supported by this API (identical to [KEY_LEN])
|
|
||||||
pub const KEY_MIN: usize = KEY_LEN;
|
|
||||||
/// maximal key length supported by this API (identical to [KEY_LEN])
|
|
||||||
pub const KEY_MAX: usize = KEY_LEN;
|
|
||||||
/// minimal output length supported by this API (identical [OUT_LEN])
|
|
||||||
pub const OUT_MIN: usize = OUT_LEN;
|
|
||||||
/// maximal output length supported by this API (identical [OUT_LEN])
|
|
||||||
pub const OUT_MAX: usize = OUT_LEN;
|
|
||||||
|
|
||||||
/// Hashes the given `data` with the [Blake2bMac<U32>] hash function under the given `key`.
|
|
||||||
/// The [KEY_LEN] and [OUT_LEN] are both set to 32 bytes (or 256 bits).
|
|
||||||
///
|
|
||||||
/// # Examples
|
|
||||||
///
|
|
||||||
///```rust
|
|
||||||
/// # use rosenpass_ciphers::subtle::blake2b::hash;
|
|
||||||
/// use rosenpass_to::To;
|
|
||||||
/// let zero_key: [u8; 32] = [0; 32];
|
|
||||||
/// let data: [u8; 32] = [255; 32];
|
|
||||||
/// // buffer for the hash output
|
|
||||||
/// let mut hash_data: [u8; 32] = [0u8; 32];
|
|
||||||
///
|
|
||||||
/// assert!(hash(&zero_key, &data).to(&mut hash_data).is_ok(), "Hashing has to return OK result");
|
|
||||||
///```
|
|
||||||
///
|
|
||||||
#[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(())
|
|
||||||
})
|
|
||||||
}
|
|
||||||
@@ -1,99 +0,0 @@
|
|||||||
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};
|
|
||||||
|
|
||||||
/// The key length is 32 bytes or 256 bits.
|
|
||||||
pub const KEY_LEN: usize = typenum2const! { <AeadImpl as KeySizeUser>::KeySize };
|
|
||||||
/// The MAC tag length is 16 bytes or 128 bits.
|
|
||||||
pub const TAG_LEN: usize = typenum2const! { <AeadImpl as AeadCore>::TagSize };
|
|
||||||
/// The nonce length is 12 bytes or 96 bits.
|
|
||||||
pub const NONCE_LEN: usize = typenum2const! { <AeadImpl as AeadCore>::NonceSize };
|
|
||||||
|
|
||||||
/// Encrypts using ChaCha20Poly1305 as implemented in [RustCrypto](https://github.com/RustCrypto/AEADs/tree/master/chacha20poly1305).
|
|
||||||
/// `key` MUST be chosen (pseudo-)randomly and `nonce` MOST NOT be reused. The `key` slice MUST have
|
|
||||||
/// a length of [KEY_LEN]. The `nonce` slice MUST have a length of [NONCE_LEN]. The last [TAG_LEN] bytes
|
|
||||||
/// written in `ciphertext` are the tag guaranteeing integrity. `ciphertext` MUST have a capacity of
|
|
||||||
/// `plaintext.len()` + [TAG_LEN].
|
|
||||||
///
|
|
||||||
/// # Examples
|
|
||||||
///```rust
|
|
||||||
/// # use rosenpass_ciphers::subtle::chacha20poly1305_ietf::{encrypt, TAG_LEN, KEY_LEN, NONCE_LEN};
|
|
||||||
///
|
|
||||||
/// const PLAINTEXT_LEN: usize = 43;
|
|
||||||
/// let plaintext = "post-quantum cryptography is very important".as_bytes();
|
|
||||||
/// assert_eq!(PLAINTEXT_LEN, plaintext.len());
|
|
||||||
/// let key: &[u8] = &[0u8; KEY_LEN]; // THIS IS NOT A SECURE KEY
|
|
||||||
/// let nonce: &[u8] = &[0u8; NONCE_LEN]; // THIS IS NOT A SECURE NONCE
|
|
||||||
/// let additional_data: &[u8] = "the encrypted message is very important".as_bytes();
|
|
||||||
/// let mut ciphertext_buffer = [0u8;PLAINTEXT_LEN + TAG_LEN];
|
|
||||||
///
|
|
||||||
/// let res: anyhow::Result<()> = encrypt(&mut ciphertext_buffer, key, nonce, additional_data, plaintext);
|
|
||||||
/// assert!(res.is_ok());
|
|
||||||
/// # let expected_ciphertext: &[u8] = &[239, 104, 148, 202, 120, 32, 77, 27, 246, 206, 226, 17,
|
|
||||||
/// # 83, 78, 122, 116, 187, 123, 70, 199, 58, 130, 21, 1, 107, 230, 58, 77, 18, 152, 31, 159, 80,
|
|
||||||
/// # 151, 72, 27, 236, 137, 60, 55, 180, 31, 71, 97, 199, 12, 60, 155, 70, 221, 225, 110, 132, 191,
|
|
||||||
/// # 8, 114, 85, 4, 25];
|
|
||||||
/// # assert_eq!(expected_ciphertext, &ciphertext_buffer);
|
|
||||||
///```
|
|
||||||
#[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(())
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Decrypts a `ciphertext` and verifies the integrity of the `ciphertext` and the additional data
|
|
||||||
/// `ad`. using ChaCha20Poly1305 as implemented in [RustCrypto](https://github.com/RustCrypto/AEADs/tree/master/chacha20poly1305).
|
|
||||||
///
|
|
||||||
/// The `key` slice MUST have a length of [KEY_LEN]. The `nonce` slice MUST have a length of
|
|
||||||
/// [NONCE_LEN]. The plaintext buffer must have a capacity of `ciphertext.len()` - [TAG_LEN].
|
|
||||||
///
|
|
||||||
/// # Examples
|
|
||||||
///```rust
|
|
||||||
/// # use rosenpass_ciphers::subtle::chacha20poly1305_ietf::{decrypt, TAG_LEN, KEY_LEN, NONCE_LEN};
|
|
||||||
/// let ciphertext: &[u8] = &[239, 104, 148, 202, 120, 32, 77, 27, 246, 206, 226, 17,
|
|
||||||
/// 83, 78, 122, 116, 187, 123, 70, 199, 58, 130, 21, 1, 107, 230, 58, 77, 18, 152, 31, 159, 80,
|
|
||||||
/// 151, 72, 27, 236, 137, 60, 55, 180, 31, 71, 97, 199, 12, 60, 155, 70, 221, 225, 110, 132, 191,
|
|
||||||
/// 8, 114, 85, 4, 25]; // this is the ciphertext generated by the example for the encryption
|
|
||||||
/// const PLAINTEXT_LEN: usize = 43;
|
|
||||||
/// assert_eq!(PLAINTEXT_LEN + TAG_LEN, ciphertext.len());
|
|
||||||
///
|
|
||||||
/// let key: &[u8] = &[0u8; KEY_LEN]; // THIS IS NOT A SECURE KEY
|
|
||||||
/// let nonce: &[u8] = &[0u8; NONCE_LEN]; // THIS IS NOT A SECURE NONCE
|
|
||||||
/// let additional_data: &[u8] = "the encrypted message is very important".as_bytes();
|
|
||||||
/// let mut plaintext_buffer = [0u8; PLAINTEXT_LEN];
|
|
||||||
///
|
|
||||||
/// let res: anyhow::Result<()> = decrypt(&mut plaintext_buffer, key, nonce, additional_data, ciphertext);
|
|
||||||
/// assert!(res.is_ok());
|
|
||||||
/// let expected_plaintext = "post-quantum cryptography is very important".as_bytes();
|
|
||||||
/// assert_eq!(expected_plaintext, plaintext_buffer);
|
|
||||||
///
|
|
||||||
///```
|
|
||||||
#[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(())
|
|
||||||
}
|
|
||||||
@@ -1,117 +0,0 @@
|
|||||||
use rosenpass_to::ops::copy_slice;
|
|
||||||
use rosenpass_to::To;
|
|
||||||
|
|
||||||
use zeroize::Zeroize;
|
|
||||||
|
|
||||||
/// The key length is 32 bytes or 256 bits.
|
|
||||||
pub const KEY_LEN: usize = 32; // Grrrr! Libcrux, please provide me these constants.
|
|
||||||
/// The MAC tag length is 16 bytes or 128 bits.
|
|
||||||
pub const TAG_LEN: usize = 16;
|
|
||||||
/// The nonce length is 12 bytes or 96 bits.
|
|
||||||
pub const NONCE_LEN: usize = 12;
|
|
||||||
|
|
||||||
/// Encrypts using ChaCha20Poly1305 as implemented in [libcrux](https://github.com/cryspen/libcrux).
|
|
||||||
/// Key and nonce MUST be chosen (pseudo-)randomly. The `key` slice MUST have a length of
|
|
||||||
/// [KEY_LEN]. The `nonce` slice MUST have a length of [NONCE_LEN]. The last [TAG_LEN] bytes
|
|
||||||
/// written in `ciphertext` are the tag guaranteeing integrity. `ciphertext` MUST have a capacity of
|
|
||||||
/// `plaintext.len()` + [TAG_LEN].
|
|
||||||
///
|
|
||||||
/// # Examples
|
|
||||||
///```rust
|
|
||||||
/// # use rosenpass_ciphers::subtle::chacha20poly1305_ietf_libcrux::{encrypt, TAG_LEN, KEY_LEN, NONCE_LEN};
|
|
||||||
///
|
|
||||||
/// const PLAINTEXT_LEN: usize = 43;
|
|
||||||
/// let plaintext = "post-quantum cryptography is very important".as_bytes();
|
|
||||||
/// assert_eq!(PLAINTEXT_LEN, plaintext.len());
|
|
||||||
/// let key: &[u8] = &[0u8; KEY_LEN]; // THIS IS NOT A SECURE KEY
|
|
||||||
/// let nonce: &[u8] = &[0u8; NONCE_LEN]; // THIS IS NOT A SECURE NONCE
|
|
||||||
/// let additional_data: &[u8] = "the encrypted message is very important".as_bytes();
|
|
||||||
/// let mut ciphertext_buffer = [0u8; PLAINTEXT_LEN + TAG_LEN];
|
|
||||||
///
|
|
||||||
/// let res: anyhow::Result<()> = encrypt(&mut ciphertext_buffer, key, nonce, additional_data, plaintext);
|
|
||||||
/// assert!(res.is_ok());
|
|
||||||
/// # let expected_ciphertext: &[u8] = &[239, 104, 148, 202, 120, 32, 77, 27, 246, 206, 226, 17,
|
|
||||||
/// # 83, 78, 122, 116, 187, 123, 70, 199, 58, 130, 21, 1, 107, 230, 58, 77, 18, 152, 31, 159, 80,
|
|
||||||
/// # 151, 72, 27, 236, 137, 60, 55, 180, 31, 71, 97, 199, 12, 60, 155, 70, 221, 225, 110, 132, 191,
|
|
||||||
/// # 8, 114, 85, 4, 25];
|
|
||||||
/// # assert_eq!(expected_ciphertext, &ciphertext_buffer);
|
|
||||||
///```
|
|
||||||
///
|
|
||||||
#[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(())
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Decrypts a `ciphertext` and verifies the integrity of the `ciphertext` and the additional data
|
|
||||||
/// `ad`. using ChaCha20Poly1305 as implemented in [libcrux](https://github.com/cryspen/libcrux).
|
|
||||||
///
|
|
||||||
/// The `key` slice MUST have a length of [KEY_LEN]. The `nonce` slice MUST have a length of
|
|
||||||
/// [NONCE_LEN]. The plaintext buffer must have a capacity of `ciphertext.len()` - [TAG_LEN].
|
|
||||||
///
|
|
||||||
/// # Examples
|
|
||||||
///```rust
|
|
||||||
/// # use rosenpass_ciphers::subtle::chacha20poly1305_ietf_libcrux::{decrypt, TAG_LEN, KEY_LEN, NONCE_LEN};
|
|
||||||
/// let ciphertext: &[u8] = &[239, 104, 148, 202, 120, 32, 77, 27, 246, 206, 226, 17,
|
|
||||||
/// 83, 78, 122, 116, 187, 123, 70, 199, 58, 130, 21, 1, 107, 230, 58, 77, 18, 152, 31, 159, 80,
|
|
||||||
/// 151, 72, 27, 236, 137, 60, 55, 180, 31, 71, 97, 199, 12, 60, 155, 70, 221, 225, 110, 132, 191,
|
|
||||||
/// 8, 114, 85, 4, 25]; // this is the ciphertext generated by the example for the encryption
|
|
||||||
/// const PLAINTEXT_LEN: usize = 43;
|
|
||||||
/// assert_eq!(PLAINTEXT_LEN + TAG_LEN, ciphertext.len());
|
|
||||||
///
|
|
||||||
/// let key: &[u8] = &[0u8; KEY_LEN]; // THIS IS NOT A SECURE KEY
|
|
||||||
/// let nonce: &[u8] = &[0u8; NONCE_LEN]; // THIS IS NOT A SECURE NONCE
|
|
||||||
/// let additional_data: &[u8] = "the encrypted message is very important".as_bytes();
|
|
||||||
/// let mut plaintext_buffer = [0u8; PLAINTEXT_LEN];
|
|
||||||
///
|
|
||||||
/// let res: anyhow::Result<()> = decrypt(&mut plaintext_buffer, key, nonce, additional_data, ciphertext);
|
|
||||||
/// assert!(res.is_ok());
|
|
||||||
/// let expected_plaintext = "post-quantum cryptography is very important".as_bytes();
|
|
||||||
/// assert_eq!(expected_plaintext, plaintext_buffer);
|
|
||||||
///
|
|
||||||
///```
|
|
||||||
#[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(())
|
|
||||||
}
|
|
||||||
@@ -1,67 +0,0 @@
|
|||||||
use anyhow::ensure;
|
|
||||||
use zeroize::Zeroizing;
|
|
||||||
|
|
||||||
use rosenpass_constant_time::xor;
|
|
||||||
use rosenpass_to::{ops::copy_slice, with_destination, To};
|
|
||||||
|
|
||||||
use crate::subtle::blake2b;
|
|
||||||
|
|
||||||
/// The key length, 32 bytes or 256 bits.
|
|
||||||
pub const KEY_LEN: usize = 32;
|
|
||||||
/// The minimal key length, identical to [KEY_LEN]
|
|
||||||
pub const KEY_MIN: usize = KEY_LEN;
|
|
||||||
/// The maximal key length, identical to [KEY_LEN]
|
|
||||||
pub const KEY_MAX: usize = KEY_LEN;
|
|
||||||
/// The minimal output length, see [blake2b::OUT_MIN]
|
|
||||||
pub const OUT_MIN: usize = blake2b::OUT_MIN;
|
|
||||||
/// The maximal output length, see [blake2b::OUT_MAX]
|
|
||||||
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>
|
|
||||||
///
|
|
||||||
/// # Examples
|
|
||||||
///```rust
|
|
||||||
/// # use rosenpass_ciphers::subtle::incorrect_hmac_blake2b::hash;
|
|
||||||
/// use rosenpass_to::To;
|
|
||||||
/// let key: [u8; 32] = [0; 32];
|
|
||||||
/// let data: [u8; 32] = [255; 32];
|
|
||||||
/// // buffer for the hash output
|
|
||||||
/// let mut hash_data: [u8; 32] = [0u8; 32];
|
|
||||||
///
|
|
||||||
/// assert!(hash(&key, &data).to(&mut hash_data).is_ok(), "Hashing has to return OK result");
|
|
||||||
/// # let expected_hash: &[u8] = &[5, 152, 135, 141, 151, 106, 147, 8, 220, 95, 38, 66, 29, 33, 3,
|
|
||||||
/// 104, 250, 114, 131, 119, 27, 56, 59, 44, 11, 67, 230, 113, 112, 20, 80, 103];
|
|
||||||
/// # assert_eq!(hash_data, expected_hash);
|
|
||||||
///```
|
|
||||||
///
|
|
||||||
#[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(())
|
|
||||||
})
|
|
||||||
}
|
|
||||||
@@ -1,13 +0,0 @@
|
|||||||
/// This module provides the following cryptographic schemes:
|
|
||||||
/// - [blake2b]: The blake2b hash function
|
|
||||||
/// - [chacha20poly1305_ietf]: The Chacha20Poly1305 AEAD as implemented in [RustCrypto](https://crates.io/crates/chacha20poly1305) (only used when the feature `experiment_libcrux` is disabled.
|
|
||||||
/// - [chacha20poly1305_ietf_libcrux]: The Chacha20Poly1305 AEAD as implemented in [libcrux](https://github.com/cryspen/libcrux) (only used when the feature `experiment_libcrux` is enabled.
|
|
||||||
/// - [incorrect_hmac_blake2b]: An (incorrect) hmac based on [blake2b].
|
|
||||||
/// - [xchacha20poly1305_ietf] The Chacha20Poly1305 AEAD as implemented in [RustCrypto](https://crates.io/crates/chacha20poly1305)
|
|
||||||
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;
|
|
||||||
@@ -1,108 +0,0 @@
|
|||||||
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};
|
|
||||||
|
|
||||||
/// The key length is 32 bytes or 256 bits.
|
|
||||||
pub const KEY_LEN: usize = typenum2const! { <AeadImpl as KeySizeUser>::KeySize };
|
|
||||||
/// The MAC tag length is 16 bytes or 128 bits.
|
|
||||||
pub const TAG_LEN: usize = typenum2const! { <AeadImpl as AeadCore>::TagSize };
|
|
||||||
/// The nonce length is 24 bytes or 192 bits.
|
|
||||||
pub const NONCE_LEN: usize = typenum2const! { <AeadImpl as AeadCore>::NonceSize };
|
|
||||||
|
|
||||||
/// Encrypts using XChaCha20Poly1305 as implemented in [RustCrypto](https://github.com/RustCrypto/AEADs/tree/master/chacha20poly1305).
|
|
||||||
/// `key` and `nonce` MUST be chosen (pseudo-)randomly. The `key` slice MUST have a length of
|
|
||||||
/// [KEY_LEN]. The `nonce` slice MUST have a length of [NONCE_LEN].
|
|
||||||
/// In contrast to [chacha20poly1305_ietf::encrypt](crate::subtle::chacha20poly1305_ietf::encrypt) and
|
|
||||||
/// [chacha20poly1305_ietf_libcrux::encrypt](crate::subtle::chacha20poly1305_ietf_libcrux::encrypt),
|
|
||||||
/// `nonce` is also written into `ciphertext` and therefore ciphertext MUST have a length
|
|
||||||
/// of at least [NONCE_LEN] + `plaintext.len()` + [TAG_LEN].
|
|
||||||
///
|
|
||||||
/// # Examples
|
|
||||||
///```rust
|
|
||||||
/// # use rosenpass_ciphers::subtle::xchacha20poly1305_ietf::{encrypt, TAG_LEN, KEY_LEN, NONCE_LEN};
|
|
||||||
/// const PLAINTEXT_LEN: usize = 43;
|
|
||||||
/// let plaintext = "post-quantum cryptography is very important".as_bytes();
|
|
||||||
/// assert_eq!(PLAINTEXT_LEN, plaintext.len());
|
|
||||||
/// let key: &[u8] = &[0u8; KEY_LEN]; // THIS IS NOT A SECURE KEY
|
|
||||||
/// let nonce: &[u8] = &[0u8; NONCE_LEN]; // THIS IS NOT A SECURE NONCE
|
|
||||||
/// let additional_data: &[u8] = "the encrypted message is very important".as_bytes();
|
|
||||||
/// let mut ciphertext_buffer = [0u8; NONCE_LEN + PLAINTEXT_LEN + TAG_LEN];
|
|
||||||
///
|
|
||||||
///
|
|
||||||
/// let res: anyhow::Result<()> = encrypt(&mut ciphertext_buffer, key, nonce, additional_data, plaintext);
|
|
||||||
/// # assert!(res.is_ok());
|
|
||||||
/// # let expected_ciphertext: &[u8] = &[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
|
||||||
/// # 0, 0, 0, 0, 8, 241, 229, 253, 200, 81, 248, 30, 183, 149, 134, 168, 149, 87, 109, 49, 159, 108,
|
|
||||||
/// # 206, 89, 51, 232, 232, 197, 163, 253, 254, 208, 73, 76, 253, 13, 247, 162, 133, 184, 177, 44,
|
|
||||||
/// # 73, 138, 176, 193, 61, 248, 61, 183, 164, 192, 214, 168, 4, 1, 62, 243, 36, 48, 149, 164, 6];
|
|
||||||
/// # assert_eq!(expected_ciphertext, &ciphertext_buffer);
|
|
||||||
///```
|
|
||||||
#[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(())
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Decrypts a `ciphertext` and verifies the integrity of the `ciphertext` and the additional data
|
|
||||||
/// `ad`. using XChaCha20Poly1305 as implemented in [RustCrypto](https://github.com/RustCrypto/AEADs/tree/master/chacha20poly1305).
|
|
||||||
///
|
|
||||||
/// The `key` slice MUST have a length of [KEY_LEN]. The `nonce` slice MUST have a length of
|
|
||||||
/// [NONCE_LEN]. The plaintext buffer must have a capacity of `ciphertext.len()` - [TAG_LEN] - [NONCE_LEN].
|
|
||||||
///
|
|
||||||
/// In contrast to [chacha20poly1305_ietf::decrypt](crate::subtle::chacha20poly1305_ietf::decrypt) and
|
|
||||||
/// [chacha20poly1305_ietf_libcrux::decrypt](crate::subtle::chacha20poly1305_ietf_libcrux::decrypt),
|
|
||||||
/// `ciperhtext` MUST include the as it is not given otherwise.
|
|
||||||
///
|
|
||||||
/// # Examples
|
|
||||||
///```rust
|
|
||||||
/// # use rosenpass_ciphers::subtle::xchacha20poly1305_ietf::{decrypt, TAG_LEN, KEY_LEN, NONCE_LEN};
|
|
||||||
/// let ciphertext: &[u8] = &[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
|
||||||
/// # 0, 0, 0, 0, 8, 241, 229, 253, 200, 81, 248, 30, 183, 149, 134, 168, 149, 87, 109, 49, 159, 108,
|
|
||||||
/// # 206, 89, 51, 232, 232, 197, 163, 253, 254, 208, 73, 76, 253, 13, 247, 162, 133, 184, 177, 44,
|
|
||||||
/// # 73, 138, 176, 193, 61, 248, 61, 183, 164, 192, 214, 168, 4, 1, 62, 243, 36, 48, 149, 164, 6];
|
|
||||||
/// // this is the ciphertext generated by the example for the encryption
|
|
||||||
/// const PLAINTEXT_LEN: usize = 43;
|
|
||||||
/// assert_eq!(PLAINTEXT_LEN + TAG_LEN + NONCE_LEN, ciphertext.len());
|
|
||||||
///
|
|
||||||
/// let key: &[u8] = &[0u8; KEY_LEN]; // THIS IS NOT A SECURE KEY
|
|
||||||
/// let nonce: &[u8] = &[0u8; NONCE_LEN]; // THIS IS NOT A SECURE NONCE
|
|
||||||
/// let additional_data: &[u8] = "the encrypted message is very important".as_bytes();
|
|
||||||
/// let mut plaintext_buffer = [0u8; PLAINTEXT_LEN];
|
|
||||||
///
|
|
||||||
/// let res: anyhow::Result<()> = decrypt(&mut plaintext_buffer, key, additional_data, ciphertext);
|
|
||||||
/// assert!(res.is_ok());
|
|
||||||
/// let expected_plaintext = "post-quantum cryptography is very important".as_bytes();
|
|
||||||
/// assert_eq!(expected_plaintext, plaintext_buffer);
|
|
||||||
///
|
|
||||||
///```
|
|
||||||
#[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(())
|
|
||||||
}
|
|
||||||
2
config-examples/.gitignore
vendored
@@ -1,2 +0,0 @@
|
|||||||
peer-*-*-key
|
|
||||||
peer-*-out
|
|
||||||
@@ -1,18 +0,0 @@
|
|||||||
public_key = "peer-a-public-key"
|
|
||||||
secret_key = "peer-a-secret-key"
|
|
||||||
listen = ["[::]:10001"]
|
|
||||||
verbosity = "Quiet"
|
|
||||||
|
|
||||||
[[peers]]
|
|
||||||
public_key = "peer-b-public-key"
|
|
||||||
endpoint = "localhost:10002"
|
|
||||||
key_out = "peer-a-rp-out-key"
|
|
||||||
# exchange_command = [
|
|
||||||
# "wg",
|
|
||||||
# "set",
|
|
||||||
# "wg0",
|
|
||||||
# "peer",
|
|
||||||
# "<PEER_ID>",
|
|
||||||
# "preshared-key",
|
|
||||||
# "/dev/stdin",
|
|
||||||
# ]
|
|
||||||
@@ -1,18 +0,0 @@
|
|||||||
public_key = "peer-b-public-key"
|
|
||||||
secret_key = "peer-b-secret-key"
|
|
||||||
listen = ["[::]:10002"]
|
|
||||||
verbosity = "Quiet"
|
|
||||||
|
|
||||||
[[peers]]
|
|
||||||
public_key = "peer-a-public-key"
|
|
||||||
endpoint = "localhost:10001"
|
|
||||||
key_out = "peer-b-rp-out-key"
|
|
||||||
# exchange_command = [
|
|
||||||
# "wg",
|
|
||||||
# "set",
|
|
||||||
# "wg0",
|
|
||||||
# "peer",
|
|
||||||
# "<PEER_ID>",
|
|
||||||
# "preshared-key",
|
|
||||||
# "/dev/stdin",
|
|
||||||
# ]
|
|
||||||
@@ -1,22 +0,0 @@
|
|||||||
[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"
|
|
||||||
@@ -1,5 +0,0 @@
|
|||||||
# 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.
|
|
||||||
@@ -1,79 +0,0 @@
|
|||||||
//! Constant-time comparison
|
|
||||||
|
|
||||||
use core::ptr;
|
|
||||||
|
|
||||||
/// Little endian memcmp version of quinier/memsec
|
|
||||||
/// https://github.com/quininer/memsec/blob/bbc647967ff6d20d6dccf1c85f5d9037fcadd3b0/src/lib.rs#L30
|
|
||||||
///
|
|
||||||
/// # Panic & Safety
|
|
||||||
///
|
|
||||||
/// Both input arrays must be at least of the indicated length.
|
|
||||||
///
|
|
||||||
/// See [std::ptr::read_volatile] on safety.
|
|
||||||
#[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
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
pub fn memcmp_le_test() {
|
|
||||||
// use rosenpass_constant_time::memcmp_le;
|
|
||||||
let a = [0, 1, 0, 0];
|
|
||||||
let b = [0, 0, 0, 1];
|
|
||||||
assert_eq!(-1, unsafe { memcmp_le(a.as_ptr(), b.as_ptr(), 4) });
|
|
||||||
assert_eq!(0, unsafe { memcmp_le(a.as_ptr(), a.as_ptr(), 4) });
|
|
||||||
assert_eq!(1, unsafe { memcmp_le(b.as_ptr(), a.as_ptr(), 4) });
|
|
||||||
}
|
|
||||||
|
|
||||||
/// 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>
|
|
||||||
///
|
|
||||||
/// # Examples
|
|
||||||
///
|
|
||||||
/// ```rust
|
|
||||||
/// use rosenpass_constant_time::compare;
|
|
||||||
/// let a = [0, 1, 0, 0];
|
|
||||||
/// let b = [0, 0, 0, 1];
|
|
||||||
/// assert_eq!(-1, compare(&a, &b));
|
|
||||||
/// assert_eq!(0, compare(&a, &a));
|
|
||||||
/// assert_eq!(1, compare(&b, &a));
|
|
||||||
/// ```
|
|
||||||
///
|
|
||||||
/// # Panic
|
|
||||||
///
|
|
||||||
/// This function will panic if the input arrays are of different lengths.
|
|
||||||
///
|
|
||||||
/// ```should_panic
|
|
||||||
/// use rosenpass_constant_time::compare;
|
|
||||||
/// let a = [0, 1, 0];
|
|
||||||
/// let b = [0, 0, 0, 1];
|
|
||||||
/// compare(&a, &b);
|
|
||||||
/// ```
|
|
||||||
#[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()) }
|
|
||||||
}
|
|
||||||
@@ -1,50 +0,0 @@
|
|||||||
//! Incrementing numbers
|
|
||||||
|
|
||||||
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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,19 +0,0 @@
|
|||||||
#![warn(missing_docs)]
|
|
||||||
#![warn(clippy::missing_docs_in_private_items)]
|
|
||||||
//! 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;
|
|
||||||
@@ -1,121 +0,0 @@
|
|||||||
//! memcmp
|
|
||||||
|
|
||||||
/// 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.
|
|
||||||
///
|
|
||||||
/// ## Examples
|
|
||||||
///
|
|
||||||
/// ```rust
|
|
||||||
/// use rosenpass_constant_time::memcmp;
|
|
||||||
/// let a = [0, 0, 0, 0];
|
|
||||||
/// let b = [0, 0, 0, 1];
|
|
||||||
/// let c = [0, 0, 0];
|
|
||||||
/// assert!(memcmp(&a, &a));
|
|
||||||
/// assert!(!memcmp(&a, &b));
|
|
||||||
/// assert!(!memcmp(&a, &c));
|
|
||||||
/// ```
|
|
||||||
#[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"
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,36 +0,0 @@
|
|||||||
//! xor
|
|
||||||
|
|
||||||
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);
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
@@ -1,44 +0,0 @@
|
|||||||
#! /usr/bin/env bash
|
|
||||||
|
|
||||||
set -e -o pipefail
|
|
||||||
|
|
||||||
OUTPUT_DIR="target/grcov"
|
|
||||||
|
|
||||||
log() {
|
|
||||||
echo >&2 "$@"
|
|
||||||
}
|
|
||||||
|
|
||||||
exc() {
|
|
||||||
echo '$' "$@"
|
|
||||||
"$@"
|
|
||||||
}
|
|
||||||
|
|
||||||
main() {
|
|
||||||
exc cd "$(dirname "$0")"
|
|
||||||
|
|
||||||
local open="0"
|
|
||||||
if [[ "$1" == "--open" ]]; then
|
|
||||||
open="1"
|
|
||||||
fi
|
|
||||||
|
|
||||||
exc cargo llvm-cov --all-features --workspace --doctests
|
|
||||||
|
|
||||||
exc rm -rf "${OUTPUT_DIR}"
|
|
||||||
exc mkdir -p "${OUTPUT_DIR}"
|
|
||||||
exc grcov target/llvm-cov-target/ --llvm -s . --branch \
|
|
||||||
--binary-path ./target/llvm-cov-target/debug/deps \
|
|
||||||
--ignore-not-existing --ignore '../*' --ignore "/*" \
|
|
||||||
--excl-line '^\s*#\[(derive|repr)\(' \
|
|
||||||
-t lcov,html,markdown -o "${OUTPUT_DIR}"
|
|
||||||
|
|
||||||
if (( "${open}" == 1 )); then
|
|
||||||
xdg-open "${PWD}/${OUTPUT_DIR}/html/index.html"
|
|
||||||
fi
|
|
||||||
|
|
||||||
log ""
|
|
||||||
log "Generated reports in \"${PWD}/${OUTPUT_DIR}\"."
|
|
||||||
log "Open \"${PWD}/${OUTPUT_DIR}/html/index.html\" to view HTML report."
|
|
||||||
log ""
|
|
||||||
}
|
|
||||||
|
|
||||||
main "$@"
|
|
||||||
13
doc/check.sh
@@ -1,13 +0,0 @@
|
|||||||
#!/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
|
|
||||||
119
doc/rp.1
@@ -1,119 +0,0 @@
|
|||||||
.Dd $Mdocdate$
|
|
||||||
.Dt RP 1
|
|
||||||
.Os
|
|
||||||
.Sh NAME
|
|
||||||
.Nm rp
|
|
||||||
.Nd high-level interface to rosenpass
|
|
||||||
.Sh SYNOPSIS
|
|
||||||
.Nm
|
|
||||||
.Op Ar explain
|
|
||||||
.Op Ar verbose
|
|
||||||
.Ar genkey Ar ... | Ar pubkey ... | Ar exchange ...
|
|
||||||
.Nm
|
|
||||||
.Op ...
|
|
||||||
.Ar genkey PRIVATE_KEYS_DIR
|
|
||||||
.Nm
|
|
||||||
.Op ...
|
|
||||||
.Ar pubkey Ar PRIVATE_KEYS_DIR Ar PUBLIC_KEYS_DIR
|
|
||||||
.Nm
|
|
||||||
.Op ...
|
|
||||||
.\" Splitting this across several lines
|
|
||||||
.Ar exchange Ar PRIVATE_KEYS_DIR
|
|
||||||
.Op dev <device>
|
|
||||||
.Op listen <ip>:<port>
|
|
||||||
.\" Because the peer argument is complicated, it would be heel to represent it
|
|
||||||
.\" in mdoc... Using an ugly hack instead, thereby losing semantic.
|
|
||||||
[peer PUBLIC_KEYS_DIR [endpoint <ip>:<port>] [persistent-keepalive <interval>]
|
|
||||||
[allowed-ips <ip1>/<cidr1>[,<ip2>/<cidr2>] ...]] ...
|
|
||||||
.Sh DESCRIPTION
|
|
||||||
The
|
|
||||||
.Nm
|
|
||||||
program
|
|
||||||
is used to build a VPN with WireGuard and Rosenpass.
|
|
||||||
.Pp
|
|
||||||
The optional
|
|
||||||
.Op explain
|
|
||||||
and
|
|
||||||
.Op verbose
|
|
||||||
options can be used to obtain further help or to enable a detailed view on the
|
|
||||||
operations, respectively.
|
|
||||||
.Ss COMMANDS
|
|
||||||
.Bl -tag -width Ds
|
|
||||||
.It Ar genkey Ar PRIVATE_KEYS_DIR
|
|
||||||
Creates a new directory with appropriate permissions and generates all the
|
|
||||||
necessary private keys required for a peer to participate in a rosenpass
|
|
||||||
connection.
|
|
||||||
.It Ar pubkey Ar PRIVATE_KEYS_DIR Ar PUBLIC_KEYS_DIR
|
|
||||||
Creates a fresh directory at
|
|
||||||
.Ar PUBLIC_KEYS_DIR ,
|
|
||||||
which contains the extracted public keys from the private keys generated by
|
|
||||||
.Ar genkey
|
|
||||||
and located inside
|
|
||||||
.Ar PRIVATE_KEYS_DIR .
|
|
||||||
.It Ar exchange Ar PRIVATE_KEYS_DIR [dev <device>] [listen <ip>:<port>] [PEERS]
|
|
||||||
Starts the VPN on interface
|
|
||||||
.Ar device ,
|
|
||||||
listening on the provided IP and port combination, allowing connections from
|
|
||||||
.Ar PEERS .
|
|
||||||
.El
|
|
||||||
.Sh EXIT STATUS
|
|
||||||
.Ex -std
|
|
||||||
.Sh EXAMPLES
|
|
||||||
In this example, we will assume that the server has an interface bound to
|
|
||||||
192.168.0.1, that accepts incoming connections on port 9999/UDP for Rosenpass
|
|
||||||
and port 10000/UDP for WireGuard.
|
|
||||||
.Pp
|
|
||||||
To create a VPN connection, start by generating secret keys on both hosts.
|
|
||||||
.Bd -literal -offset indent
|
|
||||||
rp genkey server.rosenpass-secret
|
|
||||||
rp genkey client.rosenpass-secret
|
|
||||||
.Ed
|
|
||||||
.Pp
|
|
||||||
Extract the public keys:
|
|
||||||
.Bd -literal -offset indent
|
|
||||||
rp pubkey server.rosenpass-secret server.rosenpass-public
|
|
||||||
rp pubkey client.rosenpass-secret client.rosenpass-public
|
|
||||||
.Ed
|
|
||||||
.Pp
|
|
||||||
Copy the
|
|
||||||
.Qq -public
|
|
||||||
directories to the other peers and then start the VPN.
|
|
||||||
On the server:
|
|
||||||
.Bd -literal -offset indent
|
|
||||||
sudo rp exchange server.rosenpass-secret dev rosenpass0 listen 192.168.0.1:9999 \\
|
|
||||||
peer client.rosenpass-public allowed-ips fe80::/64
|
|
||||||
.Ed
|
|
||||||
.Pp
|
|
||||||
On the client:
|
|
||||||
.Bd -literal -offset indent
|
|
||||||
sudo rp exchange client.rosenpass-secret dev rosenpass 0 \\
|
|
||||||
peer server.rosenpass-public endpoint 192.168.0.1:9999 allowed-ips fe80::/64
|
|
||||||
.Ed
|
|
||||||
.Pp
|
|
||||||
Assign IP addresses:
|
|
||||||
.Bd -literal -offset indent
|
|
||||||
sudo ip a add fe80::1/64 dev rosenpass0 # Server
|
|
||||||
sudo ip a add fe80::2/64 dev rosenpass0 # Client
|
|
||||||
.Ed
|
|
||||||
.Pp
|
|
||||||
Test the connection by pinging the server on the client machine:
|
|
||||||
.Bd -literal -offset indent
|
|
||||||
ping fe80::1%rosenpass0 # Client
|
|
||||||
.Ed
|
|
||||||
.Pp
|
|
||||||
You can watch how rosenpass replaces the WireGuard PSK with the following:
|
|
||||||
.Bd -literal -offset indent
|
|
||||||
watch -n 0.2 'wg show all; wg show all preshared-keys'
|
|
||||||
.Ed
|
|
||||||
.Sh SEE ALSO
|
|
||||||
.Xr rosenpass 1 ,
|
|
||||||
.Xr wg 1
|
|
||||||
.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 Clara Engler
|
|
||||||
.Sh BUGS
|
|
||||||
The bugs are tracked at
|
|
||||||
.Lk https://github.com/rosenpass/rosenpass/issues .
|
|
||||||
60
flake.lock
generated
@@ -8,11 +8,11 @@
|
|||||||
"rust-analyzer-src": "rust-analyzer-src"
|
"rust-analyzer-src": "rust-analyzer-src"
|
||||||
},
|
},
|
||||||
"locked": {
|
"locked": {
|
||||||
"lastModified": 1728282832,
|
"lastModified": 1674240251,
|
||||||
"narHash": "sha256-I7AbcwGggf+CHqpyd/9PiAjpIBGTGx5woYHqtwxaV7I=",
|
"narHash": "sha256-AVMmf/CtcGensTZmMicToDpOwySEGNKYgRPC7lu3m8w=",
|
||||||
"owner": "nix-community",
|
"owner": "nix-community",
|
||||||
"repo": "fenix",
|
"repo": "fenix",
|
||||||
"rev": "1ec71be1f4b8f3105c5d38da339cb061fefc43f4",
|
"rev": "d8067f4d1d3d30732703209bec5ca7d62aaececc",
|
||||||
"type": "github"
|
"type": "github"
|
||||||
},
|
},
|
||||||
"original": {
|
"original": {
|
||||||
@@ -22,15 +22,12 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"flake-utils": {
|
"flake-utils": {
|
||||||
"inputs": {
|
|
||||||
"systems": "systems"
|
|
||||||
},
|
|
||||||
"locked": {
|
"locked": {
|
||||||
"lastModified": 1726560853,
|
"lastModified": 1667395993,
|
||||||
"narHash": "sha256-X6rJYSESBVr3hBoH0WbKE5KvhPU5bloyZ2L4K60/fPQ=",
|
"narHash": "sha256-nuEHfE/LcWyuSWnS8t12N1wc105Qtau+/OdUAjtQ0rA=",
|
||||||
"owner": "numtide",
|
"owner": "numtide",
|
||||||
"repo": "flake-utils",
|
"repo": "flake-utils",
|
||||||
"rev": "c1dfcf08411b08f6b8615f7d8971a2bfa81d5e8a",
|
"rev": "5aed5285a952e0b949eb3ba02c12fa4fcfef535f",
|
||||||
"type": "github"
|
"type": "github"
|
||||||
},
|
},
|
||||||
"original": {
|
"original": {
|
||||||
@@ -41,16 +38,29 @@
|
|||||||
},
|
},
|
||||||
"nixpkgs": {
|
"nixpkgs": {
|
||||||
"locked": {
|
"locked": {
|
||||||
"lastModified": 1728193676,
|
"lastModified": 1672968032,
|
||||||
"narHash": "sha256-PbDWAIjKJdlVg+qQRhzdSor04bAPApDqIv2DofTyynk=",
|
"narHash": "sha256-26Jns3GmHem44a06UN5Rj/KOD9qNJThyQrom02Ijur8=",
|
||||||
"owner": "NixOS",
|
"owner": "NixOS",
|
||||||
"repo": "nixpkgs",
|
"repo": "nixpkgs",
|
||||||
"rev": "ecbc1ca8ffd6aea8372ad16be9ebbb39889e55b6",
|
"rev": "2dea8991d89b9f1e78d874945f78ca15f6954289",
|
||||||
|
"type": "github"
|
||||||
|
},
|
||||||
|
"original": {
|
||||||
|
"id": "nixpkgs",
|
||||||
|
"type": "indirect"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"nixpkgs-unstable": {
|
||||||
|
"locked": {
|
||||||
|
"lastModified": 1676496762,
|
||||||
|
"narHash": "sha256-GFAxjaTgh8KJ8q7BYaI4EVGI5K98ooW70fG/83rSb08=",
|
||||||
|
"owner": "NixOS",
|
||||||
|
"repo": "nixpkgs",
|
||||||
|
"rev": "1bddde315297c092712b0ef03d9def7a474b28ae",
|
||||||
"type": "github"
|
"type": "github"
|
||||||
},
|
},
|
||||||
"original": {
|
"original": {
|
||||||
"owner": "NixOS",
|
"owner": "NixOS",
|
||||||
"ref": "nixos-24.05",
|
|
||||||
"repo": "nixpkgs",
|
"repo": "nixpkgs",
|
||||||
"type": "github"
|
"type": "github"
|
||||||
}
|
}
|
||||||
@@ -59,17 +69,18 @@
|
|||||||
"inputs": {
|
"inputs": {
|
||||||
"fenix": "fenix",
|
"fenix": "fenix",
|
||||||
"flake-utils": "flake-utils",
|
"flake-utils": "flake-utils",
|
||||||
"nixpkgs": "nixpkgs"
|
"nixpkgs": "nixpkgs",
|
||||||
|
"nixpkgs-unstable": "nixpkgs-unstable"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"rust-analyzer-src": {
|
"rust-analyzer-src": {
|
||||||
"flake": false,
|
"flake": false,
|
||||||
"locked": {
|
"locked": {
|
||||||
"lastModified": 1728249780,
|
"lastModified": 1674162026,
|
||||||
"narHash": "sha256-J269DvCI5dzBmPrXhAAtj566qt0b22TJtF3TIK+tMsI=",
|
"narHash": "sha256-iY0bxoVE7zAZmp0BB/m5hZW5pWHUfgntDvc1m2zyt/U=",
|
||||||
"owner": "rust-lang",
|
"owner": "rust-lang",
|
||||||
"repo": "rust-analyzer",
|
"repo": "rust-analyzer",
|
||||||
"rev": "2b750da1a1a2c1d2c70896108d7096089842d877",
|
"rev": "6e52c64031825920983515b9e975e93232739f7f",
|
||||||
"type": "github"
|
"type": "github"
|
||||||
},
|
},
|
||||||
"original": {
|
"original": {
|
||||||
@@ -78,21 +89,6 @@
|
|||||||
"repo": "rust-analyzer",
|
"repo": "rust-analyzer",
|
||||||
"type": "github"
|
"type": "github"
|
||||||
}
|
}
|
||||||
},
|
|
||||||
"systems": {
|
|
||||||
"locked": {
|
|
||||||
"lastModified": 1681028828,
|
|
||||||
"narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=",
|
|
||||||
"owner": "nix-systems",
|
|
||||||
"repo": "default",
|
|
||||||
"rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e",
|
|
||||||
"type": "github"
|
|
||||||
},
|
|
||||||
"original": {
|
|
||||||
"owner": "nix-systems",
|
|
||||||
"repo": "default",
|
|
||||||
"type": "github"
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"root": "root",
|
"root": "root",
|
||||||
|
|||||||
273
flake.nix
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
inputs = {
|
inputs = {
|
||||||
nixpkgs.url = "github:NixOS/nixpkgs/nixos-24.05";
|
nixpkgs-unstable.url = "github:NixOS/nixpkgs";
|
||||||
flake-utils.url = "github:numtide/flake-utils";
|
flake-utils.url = "github:numtide/flake-utils";
|
||||||
|
|
||||||
# for rust nightly with llvm-tools-preview
|
# for rust nightly with llvm-tools-preview
|
||||||
@@ -11,15 +11,6 @@
|
|||||||
outputs = { self, nixpkgs, flake-utils, ... }@inputs:
|
outputs = { self, nixpkgs, flake-utils, ... }@inputs:
|
||||||
nixpkgs.lib.foldl (a: b: nixpkgs.lib.recursiveUpdate a b) { } [
|
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 ###
|
### Actual Rosenpass Package and Docker Container Images ###
|
||||||
#
|
#
|
||||||
@@ -28,7 +19,6 @@
|
|||||||
"aarch64-linux"
|
"aarch64-linux"
|
||||||
|
|
||||||
# unsuported best-effort
|
# unsuported best-effort
|
||||||
"i686-linux"
|
|
||||||
"x86_64-darwin"
|
"x86_64-darwin"
|
||||||
"aarch64-darwin"
|
"aarch64-darwin"
|
||||||
# "x86_64-windows"
|
# "x86_64-windows"
|
||||||
@@ -39,35 +29,139 @@
|
|||||||
pkgs = import nixpkgs {
|
pkgs = import nixpkgs {
|
||||||
inherit system;
|
inherit system;
|
||||||
|
|
||||||
# apply our own overlay, overriding/inserting our packages as defined in ./pkgs
|
# TODO remove overlay once a fix for
|
||||||
overlays = [ self.overlays.default ];
|
# 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)"
|
||||||
|
"(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
|
||||||
|
isStatic = p.stdenv.hostPlatform.isStatic;
|
||||||
|
in
|
||||||
|
p.rustPlatform.buildRustPackage {
|
||||||
|
# metadata and source
|
||||||
|
pname = cargoToml.package.name;
|
||||||
|
version = cargoToml.package.version;
|
||||||
|
inherit src;
|
||||||
|
cargoLock = {
|
||||||
|
lockFile = src + "/Cargo.lock";
|
||||||
|
};
|
||||||
|
|
||||||
|
nativeBuildInputs = with pkgs; [
|
||||||
|
cmake # for oqs build in the oqs-sys crate
|
||||||
|
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 ];
|
||||||
|
|
||||||
|
# otherwise pkg-config tries to link non-existent dynamic libs
|
||||||
|
PKG_CONFIG_ALL_STATIC = true;
|
||||||
|
|
||||||
|
# nix defaults to building for aarch64 _without_ the armv8-a
|
||||||
|
# crypto extensions, but liboqs depens on these
|
||||||
|
preBuild =
|
||||||
|
if system == "aarch64-linux" then ''
|
||||||
|
NIX_CFLAGS_COMPILE="$NIX_CFLAGS_COMPILE -march=armv8-a+crypto"
|
||||||
|
'' else "";
|
||||||
|
|
||||||
|
preInstall = ''
|
||||||
|
install -D rp $out/bin/rp
|
||||||
|
wrapProgram $out/bin/rp --prefix PATH : "${ rpBinPath p }"
|
||||||
|
'';
|
||||||
|
|
||||||
|
# nix progated the *.dev outputs of buildInputs for static
|
||||||
|
# builds, but that is non-sense for an executables only package
|
||||||
|
postFixup =
|
||||||
|
if isStatic then ''
|
||||||
|
remove-references-to -t ${p.bash.dev} -t ${p.libsodium.dev} \
|
||||||
|
$out/nix-support/propagated-build-inputs
|
||||||
|
'' else "";
|
||||||
|
|
||||||
|
meta = with pkgs.lib; {
|
||||||
|
inherit (cargoToml.package) description homepage;
|
||||||
|
license = with licenses; [ mit asl20 ];
|
||||||
|
maintainers = [ maintainers.wucke13 ];
|
||||||
|
platforms = platforms.all;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
# 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" ];
|
||||||
};
|
};
|
||||||
in
|
in
|
||||||
{
|
rec {
|
||||||
packages = {
|
packages = rec {
|
||||||
default = pkgs.rosenpass;
|
default = rosenpass;
|
||||||
rosenpass = pkgs.rosenpass;
|
rosenpass = rpDerivation pkgs;
|
||||||
rosenpass-oci-image = pkgs.rosenpass-oci-image;
|
rosenpass-oci-image = rosenpassOCI "rosenpass";
|
||||||
rp = pkgs.rp;
|
|
||||||
|
|
||||||
release-package = pkgs.release-package;
|
# derivation for the release
|
||||||
|
release-package =
|
||||||
# for good measure, we also offer to cross compile to Linux on Arm
|
let
|
||||||
aarch64-linux-rosenpass-static =
|
version = cargoToml.package.version;
|
||||||
pkgs.pkgsCross.aarch64-multiplatform.pkgsStatic.rosenpass;
|
package =
|
||||||
aarch64-linux-rp-static = pkgs.pkgsCross.aarch64-multiplatform.pkgsStatic.rp;
|
if pkgs.hostPlatform.isLinux then
|
||||||
}
|
packages.rosenpass-static
|
||||||
//
|
else packages.rosenpass;
|
||||||
# We only offer static builds for linux, as this is not supported on OS X
|
oci-image =
|
||||||
(nixpkgs.lib.attrsets.optionalAttrs pkgs.stdenv.isLinux {
|
if pkgs.hostPlatform.isLinux then
|
||||||
rosenpass-static = pkgs.pkgsStatic.rosenpass;
|
packages.rosenpass-static-oci-image
|
||||||
rosenpass-static-oci-image = pkgs.pkgsStatic.rosenpass-oci-image;
|
else packages.rosenpass-oci-image;
|
||||||
rp-static = pkgs.pkgsStatic.rp;
|
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 { });
|
||||||
}
|
}
|
||||||
))
|
))
|
||||||
|
|
||||||
|
|
||||||
#
|
#
|
||||||
### Linux specifics ###
|
### Linux specifics ###
|
||||||
#
|
#
|
||||||
@@ -75,73 +169,100 @@
|
|||||||
let
|
let
|
||||||
pkgs = import nixpkgs {
|
pkgs = import nixpkgs {
|
||||||
inherit system;
|
inherit system;
|
||||||
|
|
||||||
# apply our own overlay, overriding/inserting our packages as defined in ./pkgs
|
|
||||||
overlays = [ self.overlays.default ];
|
|
||||||
};
|
};
|
||||||
|
packages = self.packages.${system};
|
||||||
in
|
in
|
||||||
{
|
{
|
||||||
|
#
|
||||||
|
### Whitepaper ###
|
||||||
|
#
|
||||||
|
packages.whitepaper =
|
||||||
|
let
|
||||||
|
pkgs = import inputs.nixpkgs-unstable {
|
||||||
|
inherit system;
|
||||||
|
};
|
||||||
|
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 soulutf8 unicode-math lualatex-math
|
||||||
|
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 ###
|
### Proof and Proof Tools ###
|
||||||
#
|
#
|
||||||
packages.proverif-patched = pkgs.proverif-patched;
|
packages.proverif-patched = pkgs.proverif.overrideAttrs (old: {
|
||||||
packages.proof-proverif = pkgs.proof-proverif;
|
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
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
#
|
#
|
||||||
### Devshells ###
|
### Devshells ###
|
||||||
#
|
#
|
||||||
devShells.default = pkgs.mkShell {
|
devShells.default = pkgs.mkShell {
|
||||||
inherit (pkgs.proof-proverif) CRYPTOVERIF_LIB;
|
inherit (packages.proof-proverif) CRYPTOVERIF_LIB;
|
||||||
inputsFrom = [ pkgs.rosenpass ];
|
inputsFrom = [ packages.default ];
|
||||||
nativeBuildInputs = with pkgs; [
|
nativeBuildInputs = with pkgs; [
|
||||||
cargo-release
|
cargo-release
|
||||||
clippy
|
clippy
|
||||||
rustfmt
|
|
||||||
nodePackages.prettier
|
nodePackages.prettier
|
||||||
nushell # for the .ci/gen-workflow-files.nu script
|
|
||||||
proverif-patched
|
|
||||||
];
|
|
||||||
};
|
|
||||||
# TODO: Write this as a patched version of the default environment
|
|
||||||
devShells.fullEnv = pkgs.mkShell {
|
|
||||||
inherit (pkgs.proof-proverif) CRYPTOVERIF_LIB;
|
|
||||||
inputsFrom = [ pkgs.rosenpass ];
|
|
||||||
nativeBuildInputs = with pkgs; [
|
|
||||||
cargo-release
|
|
||||||
rustfmt
|
rustfmt
|
||||||
nodePackages.prettier
|
packages.proverif-patched
|
||||||
nushell # for the .ci/gen-workflow-files.nu script
|
|
||||||
proverif-patched
|
|
||||||
inputs.fenix.packages.${system}.complete.toolchain
|
|
||||||
pkgs.cargo-llvm-cov
|
|
||||||
pkgs.grcov
|
|
||||||
];
|
];
|
||||||
};
|
};
|
||||||
devShells.coverage = pkgs.mkShell {
|
devShells.coverage = pkgs.mkShell {
|
||||||
inputsFrom = [ pkgs.rosenpass ];
|
inputsFrom = [ packages.default ];
|
||||||
nativeBuildInputs = [
|
nativeBuildInputs = with pkgs; [ inputs.fenix.packages.${system}.complete.toolchain cargo-llvm-cov ];
|
||||||
inputs.fenix.packages.${system}.complete.toolchain
|
|
||||||
pkgs.cargo-llvm-cov
|
|
||||||
pkgs.grcov
|
|
||||||
];
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
checks = {
|
checks = {
|
||||||
systemd-rosenpass = pkgs.testers.runNixOSTest ./tests/systemd/rosenpass.nix;
|
# Blocked by https://github.com/rust-lang/rustfmt/issues/4306
|
||||||
systemd-rp = pkgs.testers.runNixOSTest ./tests/systemd/rp.nix;
|
# @dakoraa wants a coding style suitable for her accessible coding setup
|
||||||
|
# cargo-fmt = pkgs.runCommand "check-cargo-fmt"
|
||||||
cargo-fmt = pkgs.runCommand "check-cargo-fmt"
|
# { inherit (devShells.default) nativeBuildInputs buildInputs; } ''
|
||||||
{ inherit (self.devShells.${system}.default) nativeBuildInputs buildInputs; } ''
|
# cargo fmt --manifest-path=${src}/Cargo.toml --check > $out
|
||||||
cargo fmt --manifest-path=${./.}/Cargo.toml --check --all && touch $out
|
# '';
|
||||||
'';
|
|
||||||
nixpkgs-fmt = pkgs.runCommand "check-nixpkgs-fmt"
|
nixpkgs-fmt = pkgs.runCommand "check-nixpkgs-fmt"
|
||||||
{ nativeBuildInputs = [ pkgs.nixpkgs-fmt ]; } ''
|
{ nativeBuildInputs = [ pkgs.nixpkgs-fmt ]; } ''
|
||||||
nixpkgs-fmt --check ${./.} && touch $out
|
nixpkgs-fmt --check ${./.} && touch $out
|
||||||
@@ -151,8 +272,6 @@
|
|||||||
cd ${./.} && prettier --check . && touch $out
|
cd ${./.} && prettier --check . && touch $out
|
||||||
'';
|
'';
|
||||||
};
|
};
|
||||||
|
|
||||||
formatter = pkgs.nixpkgs-fmt;
|
|
||||||
}))
|
}))
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,115 +0,0 @@
|
|||||||
#!/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
@@ -1,4 +0,0 @@
|
|||||||
target
|
|
||||||
corpus
|
|
||||||
artifacts
|
|
||||||
coverage
|
|
||||||
1286
fuzz/Cargo.lock
generated
@@ -1,87 +0,0 @@
|
|||||||
[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
|
|
||||||
@@ -1,28 +0,0 @@
|
|||||||
#![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();
|
|
||||||
});
|
|
||||||
@@ -1,20 +0,0 @@
|
|||||||
#![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();
|
|
||||||
});
|
|
||||||
@@ -1,12 +0,0 @@
|
|||||||
#![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);
|
|
||||||
});
|
|
||||||
@@ -1,13 +0,0 @@
|
|||||||
#![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);
|
|
||||||
});
|
|
||||||
@@ -1,13 +0,0 @@
|
|||||||
#![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);
|
|
||||||
});
|
|
||||||
@@ -1,24 +0,0 @@
|
|||||||
#![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);
|
|
||||||
});
|
|
||||||
@@ -1,20 +0,0 @@
|
|||||||
#![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();
|
|
||||||
});
|
|
||||||
@@ -1,15 +0,0 @@
|
|||||||
#![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);
|
|
||||||
});
|
|
||||||
@@ -1,15 +0,0 @@
|
|||||||
#![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);
|
|
||||||
});
|
|
||||||
@@ -1,15 +0,0 @@
|
|||||||
#![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);
|
|
||||||
});
|
|
||||||
@@ -1,15 +0,0 @@
|
|||||||
#![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);
|
|
||||||
});
|
|
||||||
@@ -1,13 +0,0 @@
|
|||||||
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"
|
|
||||||
@@ -1,14 +0,0 @@
|
|||||||
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"
|
|
||||||
@@ -1,215 +0,0 @@
|
|||||||
#! /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 "$@"
|
|
||||||
@@ -1,40 +0,0 @@
|
|||||||
# 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.
|
|
||||||
@@ -1,105 +0,0 @@
|
|||||||
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)
|
|
||||||
@@ -1,20 +0,0 @@
|
|||||||
[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 }
|
|
||||||
|
|
||||||
[dev-dependencies]
|
|
||||||
rosenpass-secret-memory = { workspace = true }
|
|
||||||
rosenpass-constant-time = { workspace = true }
|
|
||||||
@@ -1,5 +0,0 @@
|
|||||||
# 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.
|
|
||||||
@@ -1,113 +0,0 @@
|
|||||||
//! Generic helpers for declaring bindings to liboqs kems
|
|
||||||
|
|
||||||
/// Generate bindings to a liboqs-provided KEM
|
|
||||||
macro_rules! oqs_kem {
|
|
||||||
($name:ident) => { ::paste::paste!{
|
|
||||||
#[doc = "Bindings for ::oqs_sys::kem::" [<"OQS_KEM" _ $name:snake>] "_*"]
|
|
||||||
mod [< $name:snake >] {
|
|
||||||
use rosenpass_cipher_traits::Kem;
|
|
||||||
use rosenpass_util::result::Guaranteed;
|
|
||||||
|
|
||||||
#[doc = "Bindings for ::oqs_sys::kem::" [<"OQS_KEM" _ $name:snake>] "_*"]
|
|
||||||
#[doc = ""]
|
|
||||||
#[doc = "# Examples"]
|
|
||||||
#[doc = ""]
|
|
||||||
#[doc = "```rust"]
|
|
||||||
#[doc = "use std::borrow::{Borrow, BorrowMut};"]
|
|
||||||
#[doc = "use rosenpass_cipher_traits::Kem;"]
|
|
||||||
#[doc = "use rosenpass_oqs::" $name:camel " as MyKem;"]
|
|
||||||
#[doc = "use rosenpass_secret_memory::{Secret, Public};"]
|
|
||||||
#[doc = ""]
|
|
||||||
#[doc = "rosenpass_secret_memory::secret_policy_try_use_memfd_secrets();"]
|
|
||||||
#[doc = ""]
|
|
||||||
#[doc = "// Recipient generates secret key, transfers pk to sender"]
|
|
||||||
#[doc = "let mut sk = Secret::<{ MyKem::SK_LEN }>::zero();"]
|
|
||||||
#[doc = "let mut pk = Public::<{ MyKem::PK_LEN }>::zero();"]
|
|
||||||
#[doc = "MyKem::keygen(sk.secret_mut(), pk.borrow_mut());"]
|
|
||||||
#[doc = ""]
|
|
||||||
#[doc = "// Sender generates ciphertext and local shared key, sends ciphertext to recipient"]
|
|
||||||
#[doc = "let mut shk_enc = Secret::<{ MyKem::SHK_LEN }>::zero();"]
|
|
||||||
#[doc = "let mut ct = Public::<{ MyKem::CT_LEN }>::zero();"]
|
|
||||||
#[doc = "MyKem::encaps(shk_enc.secret_mut(), ct.borrow_mut(), pk.borrow());"]
|
|
||||||
#[doc = ""]
|
|
||||||
#[doc = "// Recipient decapsulates ciphertext"]
|
|
||||||
#[doc = "let mut shk_dec = Secret::<{ MyKem::SHK_LEN }>::zero();"]
|
|
||||||
#[doc = "MyKem::decaps(shk_dec.secret_mut(), sk.secret(), ct.borrow());"]
|
|
||||||
#[doc = ""]
|
|
||||||
#[doc = "// Both parties end up with the same shared key"]
|
|
||||||
#[doc = "assert!(rosenpass_constant_time::compare(shk_enc.secret_mut(), shk_dec.secret_mut()) == 0);"]
|
|
||||||
#[doc = "```"]
|
|
||||||
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 >];
|
|
||||||
}}
|
|
||||||
}
|
|
||||||
@@ -1,26 +0,0 @@
|
|||||||
#![warn(missing_docs)]
|
|
||||||
#![warn(clippy::missing_docs_in_private_items)]
|
|
||||||
//! Bindings for liboqs used in Rosenpass
|
|
||||||
|
|
||||||
/// Call into a libOQS function
|
|
||||||
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
@@ -1,39 +0,0 @@
|
|||||||
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 { };
|
|
||||||
}
|
|
||||||
|
Before Width: | Height: | Size: 122 KiB |
|
Before Width: | Height: | Size: 227 KiB |
@@ -1,5 +0,0 @@
|
|||||||
# Illustrations
|
|
||||||
|
|
||||||
## License
|
|
||||||
|
|
||||||
The graphics graphics (SVG, PDF, and PNG files) in this folder are released under the CC BY-SA 4.0 license.
|
|
||||||
|
Before Width: | Height: | Size: 725 KiB After Width: | Height: | Size: 725 KiB |
@@ -1345,7 +1345,7 @@
|
|||||||
<g transform="matrix(1,0,0,1,420.66,-1031.32)">
|
<g transform="matrix(1,0,0,1,420.66,-1031.32)">
|
||||||
<g transform="matrix(31.25,0,0,31.25,1431.32,1459.33)">
|
<g transform="matrix(31.25,0,0,31.25,1431.32,1459.33)">
|
||||||
</g>
|
</g>
|
||||||
<text x="1179.63px" y="1459.33px" style="font-family:'Nunito-Medium', 'Nunito';font-weight:500;font-size:31.25px;">"chaining k<tspan x="1334px 1350.47px " y="1459.33px 1459.33px ">ey</tspan> init"</text>
|
<text x="1179.63px" y="1459.33px" style="font-family:'Nunito-Medium', 'Nunito';font-weight:500;font-size:31.25px;">"k<tspan x="1207.79px 1224.25px " y="1459.33px 1459.33px ">ey</tspan> chaining init"</text>
|
||||||
</g>
|
</g>
|
||||||
</g>
|
</g>
|
||||||
<g transform="matrix(0.389246,0,0,0.136584,299.374,1166.87)">
|
<g transform="matrix(0.389246,0,0,0.136584,299.374,1166.87)">
|
||||||
@@ -1437,7 +1437,7 @@
|
|||||||
<g transform="matrix(0.99675,0,0,0.996238,-597.124,-172.692)">
|
<g transform="matrix(0.99675,0,0,0.996238,-597.124,-172.692)">
|
||||||
<g transform="matrix(31.25,0,0,31.25,1492.94,1459.33)">
|
<g transform="matrix(31.25,0,0,31.25,1492.94,1459.33)">
|
||||||
</g>
|
</g>
|
||||||
<text x="1187.16px" y="1459.33px" style="font-family:'Nunito-Medium', 'Nunito';font-weight:500;font-size:31.25px;">"chaining k<tspan x="1341.54px 1358px " y="1459.33px 1459.33px ">ey</tspan> e<tspan x="1398.88px " y="1459.33px ">x</tspan>tr<tspan x="1437.88px " y="1459.33px ">a</tspan>ct"</text>
|
<text x="1187.16px" y="1459.33px" style="font-family:'Nunito-Medium', 'Nunito';font-weight:500;font-size:31.25px;">"k<tspan x="1215.32px 1231.79px " y="1459.33px 1459.33px ">ey</tspan> chaining e<tspan x="1398.88px " y="1459.33px ">x</tspan>tr<tspan x="1437.88px " y="1459.33px ">a</tspan>ct"</text>
|
||||||
</g>
|
</g>
|
||||||
<g transform="matrix(0.99675,0,0,0.996238,-380.054,-779.158)">
|
<g transform="matrix(0.99675,0,0,0.996238,-380.054,-779.158)">
|
||||||
<g transform="matrix(31.25,0,0,31.25,1463.54,1459.33)">
|
<g transform="matrix(31.25,0,0,31.25,1463.54,1459.33)">
|
||||||
|
|||||||
|
Before Width: | Height: | Size: 218 KiB After Width: | Height: | Size: 218 KiB |
218
papers/prftree.d2
Normal file
@@ -0,0 +1,218 @@
|
|||||||
|
root: 0 { shape: text }
|
||||||
|
PROTOCOL: "PROTOCOL" { shape: text }
|
||||||
|
|
||||||
|
protocol_comment: 'PROTOCOL = "rosenpass 1 rosenpass.eu aead=chachapoly1305 dprf=blake2s ekem=lightsaber skem=mceliece460896 xaead=xchachapoly1305"' { shape: text}
|
||||||
|
|
||||||
|
ck_init: '"chaining key init"' { shape: text }
|
||||||
|
ck_ext: '"chaining key extract"' { shape: text }
|
||||||
|
|
||||||
|
mac: '"mac"' { shape: text }
|
||||||
|
mac_param: MAC_WIRE_DATA { shape: text }
|
||||||
|
cookie: '"cookie"' { shape: text }
|
||||||
|
cookie_param: COOKIE_WIRE_DATA { shape: text }
|
||||||
|
peer_id: '"peer_id"' { shape: text }
|
||||||
|
peer_id_p1: spkm { shape: text}
|
||||||
|
peer_id_p2: spkt { shape: text}
|
||||||
|
|
||||||
|
root -> PROTOCOL
|
||||||
|
|
||||||
|
PROTOCOL -> mac -> mac_param
|
||||||
|
PROTOCOL -> cookie -> cookie_param
|
||||||
|
PROTOCOL -> peer_id -> peer_id_p1 -> peer_id_p2
|
||||||
|
PROTOCOL -> ck_init
|
||||||
|
PROTOCOL -> ck_ext
|
||||||
|
|
||||||
|
mix: '"mix"' { shape: text }
|
||||||
|
user: '"user"' { shape: text }
|
||||||
|
rp_eu: '"rosenpass.eu"' { shape: text }
|
||||||
|
wg_psk: '"wireguard psk"' { shape: text }
|
||||||
|
hs_enc: '"handshake encryption"' { shape: text }
|
||||||
|
ini_enc: '"initiator session encryption"' { shape: text }
|
||||||
|
res_enc: '"responder session encryption"' { shape: text }
|
||||||
|
|
||||||
|
ck_ext -> mix
|
||||||
|
ck_ext -> user -> rp_eu -> wg_psk
|
||||||
|
ck_ext -> hs_enc
|
||||||
|
ck_ext -> ini_enc
|
||||||
|
ck_ext -> res_enc
|
||||||
|
|
||||||
|
# ck_init -> InitHello.start
|
||||||
|
|
||||||
|
InitHello {
|
||||||
|
start -> d0 \
|
||||||
|
-> m1 -> d1 \
|
||||||
|
-> m2 -> d2
|
||||||
|
|
||||||
|
d2 -> encaps_spkr.m1
|
||||||
|
encaps_spkr.d3 -> encrypt_ltk.m1
|
||||||
|
encaps_spkr.d3 -> encrypt_ltk.key
|
||||||
|
encrypt_ltk.d1 -> encrypt_auth.m1
|
||||||
|
encrypt_ltk.d1 -> encrypt_auth.key
|
||||||
|
|
||||||
|
m1: "mix" { shape: text }
|
||||||
|
m2: "mix" { shape: text }
|
||||||
|
|
||||||
|
start: '"chaining key init"' { shape: text }
|
||||||
|
d0: "spkr" { shape: circle }
|
||||||
|
d1: "sidi" { shape: circle }
|
||||||
|
d2: "epki" { shape: circle }
|
||||||
|
|
||||||
|
encaps_spkr {
|
||||||
|
m1 -> d1 \
|
||||||
|
-> m2 -> d2 \
|
||||||
|
-> m3 -> d3 \
|
||||||
|
|
||||||
|
m1: "mix" { shape: text }
|
||||||
|
m2: "mix" { shape: text }
|
||||||
|
m3: "mix" { shape: text }
|
||||||
|
|
||||||
|
d1: "spkr" { shape: circle }
|
||||||
|
d2: "sctr" { shape: circle }
|
||||||
|
d3: "sptr" { shape: circle }
|
||||||
|
}
|
||||||
|
|
||||||
|
encrypt_ltk {
|
||||||
|
m1 -> d1
|
||||||
|
|
||||||
|
encrypt: 'Aead::enc(peer_id(spkr, spki))'
|
||||||
|
key -> encrypt: {
|
||||||
|
target-arrowhead.label: key
|
||||||
|
}
|
||||||
|
data -> encrypt: {
|
||||||
|
target-arrowhead.label: data
|
||||||
|
}
|
||||||
|
encrypt -> d1: {
|
||||||
|
source-arrowhead.label: output
|
||||||
|
}
|
||||||
|
|
||||||
|
m1: "mix" { shape: text }
|
||||||
|
key: '"handshake encryption"' { shape: text }
|
||||||
|
data: 'ref from "peer id" branch after spkt' { shape: text }
|
||||||
|
d1: "ct" { shape: diamond }
|
||||||
|
}
|
||||||
|
|
||||||
|
encrypt_auth {
|
||||||
|
m1 -> d1
|
||||||
|
|
||||||
|
encrypt: 'Aead::enc(empty())'
|
||||||
|
key -> encrypt: {
|
||||||
|
target-arrowhead.label: key
|
||||||
|
}
|
||||||
|
encrypt -> d1: {
|
||||||
|
source-arrowhead.label: output
|
||||||
|
}
|
||||||
|
|
||||||
|
m1: "mix" { shape: text }
|
||||||
|
key: '"handshake encryption"' { shape: text }
|
||||||
|
d1: "ct" { shape: diamond }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
RespHello {
|
||||||
|
start -> d0 -> m1 -> d1
|
||||||
|
d1 -> encaps_epki.m1
|
||||||
|
encaps_epki.d3 -> encaps_spki.m1
|
||||||
|
encaps_spki.d3 -> m2 -> d2
|
||||||
|
d2 -> encrypt_auth.m1
|
||||||
|
|
||||||
|
store_biscuit -> d2
|
||||||
|
"pidi" -> store_biscuit {
|
||||||
|
target-arrowhead.label: "field=peerid"
|
||||||
|
}
|
||||||
|
encaps_spki.d3 -> store_biscuit {
|
||||||
|
target-arrowhead.label: "field=ck"
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
m1: "mix" { shape: text }
|
||||||
|
m2: "mix" { shape: text }
|
||||||
|
|
||||||
|
start: '(state from InitHello)' { shape: text }
|
||||||
|
d0: "sidr" { shape: circle }
|
||||||
|
d1: "sidi" { shape: circle }
|
||||||
|
d2: "biscuit" { shape: diamond }
|
||||||
|
|
||||||
|
store_biscuit: "store_biscuit()"
|
||||||
|
|
||||||
|
encaps_epki {
|
||||||
|
m1 -> d1 \
|
||||||
|
-> m2 -> d2 \
|
||||||
|
-> m3 -> d3 \
|
||||||
|
|
||||||
|
m1: "mix" { shape: text }
|
||||||
|
m2: "mix" { shape: text }
|
||||||
|
m3: "mix" { shape: text }
|
||||||
|
|
||||||
|
d1: "epki" { shape: circle }
|
||||||
|
d2: "ecti" { shape: circle }
|
||||||
|
d3: "epti" { shape: circle }
|
||||||
|
}
|
||||||
|
|
||||||
|
encaps_spki {
|
||||||
|
m1 -> d1 \
|
||||||
|
-> m2 -> d2 \
|
||||||
|
-> m3 -> d3 \
|
||||||
|
|
||||||
|
m1: "mix" { shape: text }
|
||||||
|
m2: "mix" { shape: text }
|
||||||
|
m3: "mix" { shape: text }
|
||||||
|
|
||||||
|
d1: "spki" { shape: circle }
|
||||||
|
d2: "scti" { shape: circle }
|
||||||
|
d3: "spti" { shape: circle }
|
||||||
|
}
|
||||||
|
|
||||||
|
encrypt_auth {
|
||||||
|
m1 -> d1
|
||||||
|
|
||||||
|
encrypt: 'Aead::enc(empty())'
|
||||||
|
key -> encrypt: {
|
||||||
|
target-arrowhead.label: key
|
||||||
|
}
|
||||||
|
encrypt -> d1: {
|
||||||
|
source-arrowhead.label: output
|
||||||
|
}
|
||||||
|
|
||||||
|
m1: "mix" { shape: text }
|
||||||
|
key: '"handshake encryption"' { shape: text }
|
||||||
|
d1: "ct" { shape: diamond }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
InitConf {
|
||||||
|
start -> d0 -> m1 -> d1 -> encrypt_auth.m1
|
||||||
|
|
||||||
|
encrypt_auth.d1 -> ol1 -> o1
|
||||||
|
encrypt_auth.d1 -> ol2 -> o2
|
||||||
|
encrypt_auth.d1 -> ol3 -> o3
|
||||||
|
|
||||||
|
m1: "mix" { shape: text }
|
||||||
|
|
||||||
|
start: '(state from RespHello)' { shape: text }
|
||||||
|
d0: "sidi" { shape: circle }
|
||||||
|
d1: "sidr" { shape: circle }
|
||||||
|
|
||||||
|
ol1: '"wireguard psk"' { shape: text }
|
||||||
|
ol2: '"initiator session encryption"' { shape: text }
|
||||||
|
ol3: '"responder session encryption"' { shape: text}
|
||||||
|
o2: "" { shape: page }
|
||||||
|
o1: "" { shape: step }
|
||||||
|
o2: "" { shape: step }
|
||||||
|
o3: "" { shape: step }
|
||||||
|
|
||||||
|
encrypt_auth {
|
||||||
|
m1 -> d1
|
||||||
|
|
||||||
|
encrypt: 'Aead::enc(empty())'
|
||||||
|
key -> encrypt: {
|
||||||
|
target-arrowhead.label: key
|
||||||
|
}
|
||||||
|
encrypt -> d1: {
|
||||||
|
source-arrowhead.label: output
|
||||||
|
}
|
||||||
|
|
||||||
|
m1: "mix" { shape: text }
|
||||||
|
key: '"handshake encryption"' { shape: text }
|
||||||
|
d1: "ct" { shape: diamond }
|
||||||
|
}
|
||||||
|
}
|
||||||
823
papers/prftree.svg
Normal file
|
After Width: | Height: | Size: 847 KiB |
@@ -23,7 +23,3 @@ inside `papers/`. The PDF files will be located directly in `papers/`.
|
|||||||
The version info is using gitinfo2. To use the setup one has to run the `papers/tex/gitinfo2.sh` script. In local copies it's also possible to add this as a post-checkout or post-commit hook to keep it automatically up to date.
|
The version info is using gitinfo2. To use the setup one has to run the `papers/tex/gitinfo2.sh` script. In local copies it's also possible to add this as a post-checkout or post-commit hook to keep it automatically up to date.
|
||||||
|
|
||||||
The version information in the footer automatically includes a “draft”. This can be removed by tagging a release version using `\jobname-release`, e.h. `whitepaper-release` for the `whitepaper.md` file.
|
The version information in the footer automatically includes a “draft”. This can be removed by tagging a release version using `\jobname-release`, e.h. `whitepaper-release` for the `whitepaper.md` file.
|
||||||
|
|
||||||
## Licensing of assets
|
|
||||||
|
|
||||||
The text files and graphics in this folder (i.e. whitepaper.md, the SVG, PDF, and PNG files in the graphics/ folder) are released under the CC BY-SA 4.0 license.
|
|
||||||
|
|||||||
81
papers/sequencing.d2
Normal file
@@ -0,0 +1,81 @@
|
|||||||
|
Protocol: {
|
||||||
|
shape: sequence_diagram
|
||||||
|
ini: "Initiator"
|
||||||
|
res: "Responder"
|
||||||
|
ini -> res: "InitHello"
|
||||||
|
res -> ini: "RespHello"
|
||||||
|
ini -> res: "InitConf"
|
||||||
|
res -> ini: "EmptyData"
|
||||||
|
}
|
||||||
|
|
||||||
|
Envelope: "Envelope" {
|
||||||
|
shape: class
|
||||||
|
type: "1"
|
||||||
|
'': 3
|
||||||
|
payload: variable
|
||||||
|
mac: 16
|
||||||
|
cookie: 16
|
||||||
|
}
|
||||||
|
|
||||||
|
Envelope.payload -> InitHello
|
||||||
|
InitHello: "InitHello (type=0x81)" {
|
||||||
|
shape: class
|
||||||
|
sidi: 4
|
||||||
|
epki: 800
|
||||||
|
sctr: 188
|
||||||
|
peerid: 32 + 16 = 48
|
||||||
|
auth: 16
|
||||||
|
}
|
||||||
|
|
||||||
|
Envelope.payload -> RespHello
|
||||||
|
RespHello: "RespHello (type=0x82)" {
|
||||||
|
shape: class
|
||||||
|
sidr: 4
|
||||||
|
sidi: 4
|
||||||
|
ecti: 768
|
||||||
|
scti: 188
|
||||||
|
biscuit: 76 + 24 + 16 = 116
|
||||||
|
auth: 16
|
||||||
|
}
|
||||||
|
|
||||||
|
Envelope.payload -> InitConf
|
||||||
|
InitConf: "InitConf (type=0x83)" {
|
||||||
|
shape: class
|
||||||
|
sidi: 4
|
||||||
|
sidr: 4
|
||||||
|
biscuit: 76 + 24 +16 = 116
|
||||||
|
auth: 16
|
||||||
|
}
|
||||||
|
|
||||||
|
Envelope.payload -> EmptyData
|
||||||
|
EmptyData: "EmptyData (type=0x84)" {
|
||||||
|
shape: class
|
||||||
|
sidx: 4
|
||||||
|
ctr: 8
|
||||||
|
auth: 16
|
||||||
|
}
|
||||||
|
|
||||||
|
Envelope.payload -> Data
|
||||||
|
Data: "Data (type=0x85)" {
|
||||||
|
shape: class
|
||||||
|
sidx: 4
|
||||||
|
ctr: 8
|
||||||
|
data: variable + 16
|
||||||
|
}
|
||||||
|
|
||||||
|
Envelope.payload -> CookieReply
|
||||||
|
CookieReply: "CookieReply (type=0x86)" {
|
||||||
|
shape: class
|
||||||
|
sidx: 4
|
||||||
|
nonce: 24
|
||||||
|
cookie: 16 + 16 = 32
|
||||||
|
}
|
||||||
|
|
||||||
|
RespHello.biscuit -> Biscuit
|
||||||
|
InitConf.biscuit -> Biscuit
|
||||||
|
Biscuit: "Biscuit" {
|
||||||
|
shape: class
|
||||||
|
peerid: 32
|
||||||
|
no: 12
|
||||||
|
ck: 32
|
||||||
|
}
|
||||||
133
papers/sequencing.svg
Normal file
|
After Width: | Height: | Size: 669 KiB |
@@ -79,8 +79,6 @@
|
|||||||
letter-csv .initial:n = ,
|
letter-csv .initial:n = ,
|
||||||
letter-content .tl_set:N = \l_letter_csv_content_tl,
|
letter-content .tl_set:N = \l_letter_csv_content_tl,
|
||||||
letter-content .initial:n=,
|
letter-content .initial:n=,
|
||||||
tableofcontents .bool_gset:N = \g__ptxcd_tableofcontents_bool,
|
|
||||||
tableofcontents .initial:n = true,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
\tl_new:N \l__markdown_sequence_tl
|
\tl_new:N \l__markdown_sequence_tl
|
||||||
|
|||||||
@@ -171,17 +171,8 @@ version={4.0},
|
|||||||
\ExplSyntaxOn
|
\ExplSyntaxOn
|
||||||
\SetTemplatePreamble{
|
\SetTemplatePreamble{
|
||||||
\hypersetup{pdftitle=\inserttitle,pdfauthor=The~Rosenpass~Project}
|
\hypersetup{pdftitle=\inserttitle,pdfauthor=The~Rosenpass~Project}
|
||||||
\exp_args:NV\tl_if_eq:nnTF \inserttitle{Rosenpass} {
|
\title{\vspace*{-2.5cm}\includegraphics[width=4cm]{RosenPass-Logo}}
|
||||||
\title{\vspace*{-2.5cm}\includegraphics[width=4cm]{RosenPass-Logo}}
|
\author{\csname insertauthor\endcsname}
|
||||||
} {
|
|
||||||
\titlehead{\centerline{\includegraphics[width=4cm]{RosenPass-Logo}}}
|
|
||||||
\title{\inserttitle}
|
|
||||||
}
|
|
||||||
\ifx\csname insertauthor\endcsname\relax
|
|
||||||
\author{}
|
|
||||||
\else
|
|
||||||
\author{\parbox{\linewidth}{\centering\insertauthor}}
|
|
||||||
\fi
|
|
||||||
\subject{\csname insertsubject\endcsname}
|
\subject{\csname insertsubject\endcsname}
|
||||||
\date{\vspace{-1cm}}
|
\date{\vspace{-1cm}}
|
||||||
}
|
}
|
||||||
@@ -383,28 +374,29 @@ version={4.0},
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
\makeatother
|
||||||
|
\ExplSyntaxOff
|
||||||
% end of namepartpicturesetup
|
% end of namepartpicturesetup
|
||||||
|
|
||||||
\newcommand{\captionbox}[1]{{\setlength{\fboxsep}{.5ex}\colorbox{rosenpass-gray}{#1}}}
|
\newcommand{\captionbox}[1]{{\setlength{\fboxsep}{.5ex}\colorbox{rosenpass-gray}{#1}}}
|
||||||
|
|
||||||
|
\makeatletter
|
||||||
\renewenvironment{abstract}{
|
\renewenvironment{abstract}{
|
||||||
\small
|
\small
|
||||||
\begin{center}\normalfont\sectfont\nobreak\abstractname\@endparpenalty\@M\end{center}%
|
\begin{center}\normalfont\sectfont\nobreak\abstractname\@endparpenalty\@M\end{center}%
|
||||||
}{
|
}{
|
||||||
\par
|
\par
|
||||||
}
|
}
|
||||||
|
\makeatother
|
||||||
|
|
||||||
\SetTemplateBegin{
|
\SetTemplateBegin{
|
||||||
\maketitle
|
\maketitle
|
||||||
\begin{abstract}
|
\begin{abstract}
|
||||||
\noindent\csname insertabstract\endcsname
|
\noindent\csname insertabstract\endcsname
|
||||||
\end{abstract}
|
\end{abstract}
|
||||||
\bool_if:NT \g__ptxcd_tableofcontents_bool \tableofcontents
|
\tableofcontents
|
||||||
\clearpage
|
\clearpage
|
||||||
}
|
}
|
||||||
\makeatother
|
|
||||||
\ExplSyntaxOff
|
|
||||||
|
|
||||||
\SetTemplateEnd{}
|
\SetTemplateEnd{
|
||||||
|
}
|
||||||
|
|||||||