Compare commits
6 Commits
dev/karo/a
...
systemd-un
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
6b3bebb9b9 | ||
|
|
9948169127 | ||
|
|
eced56bd70 | ||
|
|
df1e195b5d | ||
|
|
e1e280c4c5 | ||
|
|
06cd178977 |
@@ -3,6 +3,11 @@ secret_key = "rp-a-secret-key"
|
|||||||
listen = ["127.0.0.1:9999"]
|
listen = ["127.0.0.1:9999"]
|
||||||
verbosity = "Verbose"
|
verbosity = "Verbose"
|
||||||
|
|
||||||
|
[api]
|
||||||
|
listen_path = []
|
||||||
|
listen_fd = []
|
||||||
|
stream_fd = []
|
||||||
|
|
||||||
[[peers]]
|
[[peers]]
|
||||||
public_key = "rp-b-public-key"
|
public_key = "rp-b-public-key"
|
||||||
endpoint = "127.0.0.1:9998"
|
endpoint = "127.0.0.1:9998"
|
||||||
|
|||||||
@@ -3,6 +3,11 @@ secret_key = "rp-b-secret-key"
|
|||||||
listen = ["127.0.0.1:9998"]
|
listen = ["127.0.0.1:9998"]
|
||||||
verbosity = "Verbose"
|
verbosity = "Verbose"
|
||||||
|
|
||||||
|
[api]
|
||||||
|
listen_path = []
|
||||||
|
listen_fd = []
|
||||||
|
stream_fd = []
|
||||||
|
|
||||||
[[peers]]
|
[[peers]]
|
||||||
public_key = "rp-a-public-key"
|
public_key = "rp-a-public-key"
|
||||||
endpoint = "127.0.0.1:9999"
|
endpoint = "127.0.0.1:9999"
|
||||||
|
|||||||
@@ -32,9 +32,9 @@ let systems_map = {
|
|||||||
# aarch64-darwin
|
# aarch64-darwin
|
||||||
# aarch64-linux
|
# aarch64-linux
|
||||||
|
|
||||||
i686-linux: ubicloud-standard-2-ubuntu-2204,
|
i686-linux: ubuntu-latest,
|
||||||
x86_64-darwin: macos-13,
|
x86_64-darwin: macos-13,
|
||||||
x86_64-linux: ubicloud-standard-2-ubuntu-2204
|
x86_64-linux: ubuntu-latest
|
||||||
}
|
}
|
||||||
|
|
||||||
let targets = (get-attr-names ".#packages"
|
let targets = (get-attr-names ".#packages"
|
||||||
@@ -61,13 +61,14 @@ mut release_workflow = {
|
|||||||
|
|
||||||
let runner_setup = [
|
let runner_setup = [
|
||||||
{
|
{
|
||||||
uses: "actions/checkout@v4"
|
uses: "actions/checkout@v3"
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
uses: "cachix/install-nix-action@v30",
|
uses: "cachix/install-nix-action@v22",
|
||||||
|
with: { nix_path: "nixpkgs=channel:nixos-unstable" }
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
uses: "cachix/cachix-action@v15",
|
uses: "cachix/cachix-action@v12",
|
||||||
with: {
|
with: {
|
||||||
name: rosenpass,
|
name: rosenpass,
|
||||||
authToken: "${{ secrets.CACHIX_AUTH_TOKEN }}"
|
authToken: "${{ secrets.CACHIX_AUTH_TOKEN }}"
|
||||||
@@ -153,7 +154,7 @@ for system in ($targets | columns) {
|
|||||||
}
|
}
|
||||||
{
|
{
|
||||||
name: Release,
|
name: Release,
|
||||||
uses: "softprops/action-gh-release@v2",
|
uses: "softprops/action-gh-release@v1",
|
||||||
with: {
|
with: {
|
||||||
draft: "${{ contains(github.ref_name, 'rc') }}",
|
draft: "${{ contains(github.ref_name, 'rc') }}",
|
||||||
prerelease: "${{ contains(github.ref_name, 'alpha') || contains(github.ref_name, 'beta') }}",
|
prerelease: "${{ contains(github.ref_name, 'alpha') || contains(github.ref_name, 'beta') }}",
|
||||||
@@ -181,7 +182,7 @@ $cachix_workflow.jobs = ($cachix_workflow.jobs | insert $"($system)---whitepaper
|
|||||||
}
|
}
|
||||||
{
|
{
|
||||||
name: "Deploy PDF artifacts",
|
name: "Deploy PDF artifacts",
|
||||||
uses: "peaceiris/actions-gh-pages@v4",
|
uses: "peaceiris/actions-gh-pages@v3",
|
||||||
with: {
|
with: {
|
||||||
github_token: "${{ secrets.GITHUB_TOKEN }}",
|
github_token: "${{ secrets.GITHUB_TOKEN }}",
|
||||||
publish_dir: result/,
|
publish_dir: result/,
|
||||||
|
|||||||
@@ -1 +0,0 @@
|
|||||||
.gitignore
|
|
||||||
103
.github/workflows/bench-primitives.yml
vendored
@@ -1,103 +0,0 @@
|
|||||||
name: rosenpass-ciphers - primitives - benchmark
|
|
||||||
|
|
||||||
permissions:
|
|
||||||
contents: write
|
|
||||||
|
|
||||||
on:
|
|
||||||
#pull_request:
|
|
||||||
push:
|
|
||||||
|
|
||||||
env:
|
|
||||||
CARGO_TERM_COLOR: always
|
|
||||||
|
|
||||||
concurrency:
|
|
||||||
group: ${{ github.workflow }}-${{ github.ref }}
|
|
||||||
cancel-in-progress: true
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
prim-benchmark:
|
|
||||||
strategy:
|
|
||||||
fail-fast: true
|
|
||||||
matrix:
|
|
||||||
system: ["x86_64-linux", "i686-linux"]
|
|
||||||
|
|
||||||
runs-on: ubicloud-standard-2
|
|
||||||
defaults:
|
|
||||||
run:
|
|
||||||
shell: bash
|
|
||||||
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v5
|
|
||||||
|
|
||||||
# Install nix
|
|
||||||
|
|
||||||
- name: Install Nix
|
|
||||||
uses: cachix/install-nix-action@v27 # A popular action for installing Nix
|
|
||||||
with:
|
|
||||||
extra_nix_config: |
|
|
||||||
experimental-features = nix-command flakes
|
|
||||||
access-tokens = github.com=${{ secrets.GITHUB_TOKEN }}
|
|
||||||
|
|
||||||
# Set up environment
|
|
||||||
|
|
||||||
- name: 🛠️ Prepare Benchmark Path
|
|
||||||
env:
|
|
||||||
EVENT_NAME: ${{ github.event_name }}
|
|
||||||
BRANCH_NAME: ${{ github.ref_name }}
|
|
||||||
PR_NUMBER: ${{ github.event.pull_request.number }}
|
|
||||||
run: |
|
|
||||||
case "$EVENT_NAME" in
|
|
||||||
"push")
|
|
||||||
echo "BENCH_PATH=branch/$BRANCH_NAME" >> $GITHUB_ENV
|
|
||||||
;;
|
|
||||||
"pull_request")
|
|
||||||
echo "BENCH_PATH=pull/$PR_NUMBER" >> $GITHUB_ENV
|
|
||||||
;;
|
|
||||||
*)
|
|
||||||
echo "don't know benchmark path for event of type $EVENT_NAME, aborting"
|
|
||||||
exit 1
|
|
||||||
esac
|
|
||||||
|
|
||||||
# Benchmarks ...
|
|
||||||
|
|
||||||
- name: 🏃🏻♀️ Benchmarks (using Nix as shell)
|
|
||||||
working-directory: ciphers
|
|
||||||
run: nix develop ".#devShells.${{ matrix.system }}.benchmarks" --command cargo bench -F bench --bench primitives --verbose -- --output-format bencher | tee ../bench-primitives.txt
|
|
||||||
|
|
||||||
- name: Extract benchmarks
|
|
||||||
uses: cryspen/benchmark-data-extract-transform@v2
|
|
||||||
with:
|
|
||||||
name: rosenpass-ciphers primitives benchmarks
|
|
||||||
tool: "cargo"
|
|
||||||
os: ${{ matrix.system }}
|
|
||||||
output-file-path: bench-primitives.txt
|
|
||||||
data-out-path: bench-primitives-os.json
|
|
||||||
|
|
||||||
- name: Fix up 'os' label in benchmark data
|
|
||||||
run: jq 'map(with_entries(.key |= if . == "os" then "operating system" else . end))' <bench-primitives-os.json >bench-primitives.json
|
|
||||||
|
|
||||||
- name: Upload benchmarks
|
|
||||||
uses: cryspen/benchmark-upload-and-plot-action@v3
|
|
||||||
with:
|
|
||||||
name: Crypto Primitives Benchmarks
|
|
||||||
group-by: "operating system,primitive,algorithm"
|
|
||||||
schema: "operating system,primitive,algorithm,implementation,operation,length"
|
|
||||||
input-data-path: bench-primitives.json
|
|
||||||
github-token: ${{ secrets.GITHUB_TOKEN }}
|
|
||||||
# NOTE: pushes to current repository
|
|
||||||
gh-repository: github.com/${{ github.repository }}
|
|
||||||
auto-push: true
|
|
||||||
fail-on-alert: true
|
|
||||||
base-path: benchmarks/
|
|
||||||
|
|
||||||
ciphers-primitives-bench-status:
|
|
||||||
if: ${{ always() }}
|
|
||||||
needs: [prim-benchmark]
|
|
||||||
runs-on: ubicloud-standard-2
|
|
||||||
steps:
|
|
||||||
- name: Successful
|
|
||||||
if: ${{ !(contains(needs.*.result, 'failure')) }}
|
|
||||||
run: exit 0
|
|
||||||
- name: Failing
|
|
||||||
if: ${{ (contains(needs.*.result, 'failure')) }}
|
|
||||||
run: exit 1
|
|
||||||
90
.github/workflows/bench-protocol.yml
vendored
@@ -1,90 +0,0 @@
|
|||||||
name: rosenpass - protocol - benchmark
|
|
||||||
|
|
||||||
permissions:
|
|
||||||
contents: write
|
|
||||||
|
|
||||||
on:
|
|
||||||
#pull_request:
|
|
||||||
push:
|
|
||||||
|
|
||||||
env:
|
|
||||||
CARGO_TERM_COLOR: always
|
|
||||||
|
|
||||||
concurrency:
|
|
||||||
group: ${{ github.workflow }}-${{ github.ref }}
|
|
||||||
cancel-in-progress: true
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
proto-benchmark:
|
|
||||||
strategy:
|
|
||||||
fail-fast: true
|
|
||||||
matrix:
|
|
||||||
system: ["x86_64-linux", "i686-linux"]
|
|
||||||
|
|
||||||
runs-on: ubicloud-standard-2
|
|
||||||
defaults:
|
|
||||||
run:
|
|
||||||
shell: bash
|
|
||||||
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v5
|
|
||||||
|
|
||||||
# Install nix
|
|
||||||
|
|
||||||
- name: Install Nix
|
|
||||||
uses: cachix/install-nix-action@v27 # A popular action for installing Nix
|
|
||||||
with:
|
|
||||||
extra_nix_config: |
|
|
||||||
experimental-features = nix-command flakes
|
|
||||||
access-tokens = github.com=${{ secrets.GITHUB_TOKEN }}
|
|
||||||
|
|
||||||
# Set up environment
|
|
||||||
|
|
||||||
- name: 🛠️ Prepare Benchmark Path
|
|
||||||
env:
|
|
||||||
EVENT_NAME: ${{ github.event_name }}
|
|
||||||
BRANCH_NAME: ${{ github.ref_name }}
|
|
||||||
PR_NUMBER: ${{ github.event.pull_request.number }}
|
|
||||||
run: |
|
|
||||||
case "$EVENT_NAME" in
|
|
||||||
"push")
|
|
||||||
echo "BENCH_PATH=branch/$BRANCH_NAME" >> $GITHUB_ENV
|
|
||||||
;;
|
|
||||||
"pull_request")
|
|
||||||
echo "BENCH_PATH=pull/$PR_NUMBER" >> $GITHUB_ENV
|
|
||||||
;;
|
|
||||||
*)
|
|
||||||
echo "don't know benchmark path for event of type $EVENT_NAME, aborting"
|
|
||||||
exit 1
|
|
||||||
esac
|
|
||||||
|
|
||||||
# Benchmarks ...
|
|
||||||
|
|
||||||
- name: 🏃🏻♀️ Benchmarks
|
|
||||||
run: nix develop ".#devShells.${{ matrix.system }}.benchmarks" --command cargo bench -p rosenpass --bench trace_handshake -F trace_bench --verbose >bench-protocol.json
|
|
||||||
|
|
||||||
- name: Upload benchmarks
|
|
||||||
uses: cryspen/benchmark-upload-and-plot-action@v3
|
|
||||||
with:
|
|
||||||
name: Protocol Benchmarks
|
|
||||||
group-by: "operating system,architecture,protocol version,run time"
|
|
||||||
schema: "operating system,architecture,protocol version,run time,name"
|
|
||||||
input-data-path: bench-protocol.json
|
|
||||||
github-token: ${{ secrets.GITHUB_TOKEN }}
|
|
||||||
# NOTE: pushes to current repository
|
|
||||||
gh-repository: github.com/${{ github.repository }}
|
|
||||||
auto-push: true
|
|
||||||
fail-on-alert: true
|
|
||||||
base-path: benchmarks/
|
|
||||||
|
|
||||||
ciphers-protocol-bench-status:
|
|
||||||
if: ${{ always() }}
|
|
||||||
needs: [proto-benchmark]
|
|
||||||
runs-on: ubicloud-standard-2
|
|
||||||
steps:
|
|
||||||
- name: Successful
|
|
||||||
if: ${{ !(contains(needs.*.result, 'failure')) }}
|
|
||||||
run: exit 0
|
|
||||||
- name: Failing
|
|
||||||
if: ${{ (contains(needs.*.result, 'failure')) }}
|
|
||||||
run: exit 1
|
|
||||||
4
.github/workflows/doc-upload.yml
vendored
@@ -13,10 +13,10 @@ jobs:
|
|||||||
|
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout code
|
- name: Checkout code
|
||||||
uses: actions/checkout@v5
|
uses: actions/checkout@v4
|
||||||
|
|
||||||
- name: Clone rosenpass-website repository
|
- name: Clone rosenpass-website repository
|
||||||
uses: actions/checkout@v5
|
uses: actions/checkout@v4
|
||||||
with:
|
with:
|
||||||
repository: rosenpass/rosenpass-website
|
repository: rosenpass/rosenpass-website
|
||||||
ref: main
|
ref: main
|
||||||
|
|||||||
288
.github/workflows/docker.yaml
vendored
@@ -1,288 +0,0 @@
|
|||||||
name: Build Docker Images
|
|
||||||
|
|
||||||
# Run this job on all non-pull-request events,
|
|
||||||
# or if Docker-related files are changed in a pull request.
|
|
||||||
on:
|
|
||||||
push:
|
|
||||||
branches:
|
|
||||||
- "main"
|
|
||||||
tags:
|
|
||||||
- "v*"
|
|
||||||
pull_request:
|
|
||||||
paths:
|
|
||||||
- "docker/Dockerfile"
|
|
||||||
- ".github/workflows/docker.yaml"
|
|
||||||
branches:
|
|
||||||
- "main"
|
|
||||||
|
|
||||||
permissions:
|
|
||||||
contents: read
|
|
||||||
packages: write
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
# --------------------------------
|
|
||||||
# 1. BUILD & TEST
|
|
||||||
# --------------------------------
|
|
||||||
build-and-test-rp:
|
|
||||||
strategy:
|
|
||||||
matrix:
|
|
||||||
arch: [amd64, arm64]
|
|
||||||
runs-on: ${{ matrix.arch == 'arm64' && 'ubuntu-24.04-arm' || 'ubuntu-latest' }}
|
|
||||||
steps:
|
|
||||||
- name: Checkout
|
|
||||||
uses: actions/checkout@v5
|
|
||||||
- name: Set up Docker Buildx
|
|
||||||
uses: docker/setup-buildx-action@v3
|
|
||||||
- name: Build (no push) and Load
|
|
||||||
id: build
|
|
||||||
uses: docker/build-push-action@v6
|
|
||||||
with:
|
|
||||||
context: .
|
|
||||||
file: docker/Dockerfile
|
|
||||||
# no pushing here, so we can test locally
|
|
||||||
push: false
|
|
||||||
# load the built image into the local Docker daemon on the runner
|
|
||||||
load: true
|
|
||||||
target: rosenpass
|
|
||||||
tags: rosenpass:test
|
|
||||||
platforms: linux/${{ matrix.arch }}
|
|
||||||
- name: Integration Test - Standalone Key Exchange
|
|
||||||
run: |
|
|
||||||
# Create separate workdirs
|
|
||||||
mkdir -p workdir-server workdir-client
|
|
||||||
|
|
||||||
# Create a Docker network
|
|
||||||
docker network create -d bridge rp
|
|
||||||
|
|
||||||
echo "=== GENERATE SERVER KEYS ==="
|
|
||||||
docker run --rm \
|
|
||||||
-v $PWD/workdir-server:/workdir \
|
|
||||||
rosenpass:test gen-keys \
|
|
||||||
--public-key=workdir/server-public \
|
|
||||||
--secret-key=workdir/server-secret
|
|
||||||
|
|
||||||
echo "=== GENERATE CLIENT KEYS ==="
|
|
||||||
docker run --rm \
|
|
||||||
-v $PWD/workdir-client:/workdir \
|
|
||||||
rosenpass:test gen-keys \
|
|
||||||
--public-key=workdir/client-public \
|
|
||||||
--secret-key=workdir/client-secret
|
|
||||||
|
|
||||||
echo "=== SHARE PUBLIC KEYS ==="
|
|
||||||
cp workdir-client/client-public workdir-server/client-public
|
|
||||||
cp workdir-server/server-public workdir-client/server-public
|
|
||||||
|
|
||||||
echo "=== START SERVER CONTAINER ==="
|
|
||||||
docker run -d --rm \
|
|
||||||
--name rpserver \
|
|
||||||
--network rp \
|
|
||||||
-v $PWD/workdir-server:/workdir \
|
|
||||||
rosenpass:test exchange \
|
|
||||||
private-key workdir/server-secret \
|
|
||||||
public-key workdir/server-public \
|
|
||||||
listen 0.0.0.0:9999 \
|
|
||||||
peer public-key workdir/client-public \
|
|
||||||
outfile workdir/server-sharedkey
|
|
||||||
|
|
||||||
# Get the container IP of the server
|
|
||||||
SERVER_IP=$(docker inspect --format='{{.NetworkSettings.Networks.rp.IPAddress}}' rpserver)
|
|
||||||
echo "SERVER_IP=$SERVER_IP"
|
|
||||||
|
|
||||||
echo "=== START CLIENT CONTAINER ==="
|
|
||||||
docker run -d --rm \
|
|
||||||
--name rpclient \
|
|
||||||
--network rp \
|
|
||||||
-v $PWD/workdir-client:/workdir \
|
|
||||||
rosenpass:test exchange \
|
|
||||||
private-key workdir/client-secret \
|
|
||||||
public-key workdir/client-public \
|
|
||||||
peer public-key workdir/server-public \
|
|
||||||
endpoint ${SERVER_IP}:9999 \
|
|
||||||
outfile workdir/client-sharedkey
|
|
||||||
|
|
||||||
echo "=== COMPARE SHARED KEYS ==="
|
|
||||||
echo "Waiting up to 30 seconds for the server to generate 'server-sharedkey'..."
|
|
||||||
for i in $(seq 1 30); do
|
|
||||||
if [ -f "workdir-server/server-sharedkey" ]; then
|
|
||||||
echo "server-sharedkey found!"
|
|
||||||
break
|
|
||||||
fi
|
|
||||||
sleep 1
|
|
||||||
done
|
|
||||||
sudo cmp workdir-server/server-sharedkey workdir-client/client-sharedkey
|
|
||||||
|
|
||||||
echo "Standalone Key Exchange test OK."
|
|
||||||
# --------------------------------
|
|
||||||
# 2. PUSH (only if tests pass)
|
|
||||||
# --------------------------------
|
|
||||||
docker-image-rp:
|
|
||||||
needs:
|
|
||||||
- build-and-test-rp
|
|
||||||
# Skip if this is not a PR. Then we want to push this image.
|
|
||||||
if: ${{ github.event_name != 'pull_request' }}
|
|
||||||
# Use a matrix to build for both AMD64 and ARM64
|
|
||||||
strategy:
|
|
||||||
matrix:
|
|
||||||
arch: [amd64, arm64]
|
|
||||||
# Switch the runner based on the architecture
|
|
||||||
runs-on: ${{ matrix.arch == 'arm64' && 'ubuntu-24.04-arm' || 'ubuntu-latest' }}
|
|
||||||
steps:
|
|
||||||
- name: Checkout
|
|
||||||
uses: actions/checkout@v5
|
|
||||||
|
|
||||||
- name: Docker meta
|
|
||||||
id: meta
|
|
||||||
|
|
||||||
uses: docker/metadata-action@v5
|
|
||||||
with:
|
|
||||||
images: ghcr.io/${{ github.repository_owner }}/rp
|
|
||||||
labels: |
|
|
||||||
maintainer=Karolin Varner <karo@cupdev.net>, wucke13 <wucke13@gmail.com>
|
|
||||||
org.opencontainers.image.authors=Karolin Varner <karo@cupdev.net>, wucke13 <wucke13@gmail.com>
|
|
||||||
org.opencontainers.image.title=Rosenpass
|
|
||||||
org.opencontainers.image.description=The rp command-line integrates Rosenpass and WireGuard to help you create a VPN
|
|
||||||
org.opencontainers.image.vendor=Rosenpass e.V.
|
|
||||||
org.opencontainers.image.licenses=MIT OR Apache-2.0
|
|
||||||
org.opencontainers.image.url=https://rosenpass.eu
|
|
||||||
org.opencontainers.image.documentation=https://rosenpass.eu/docs/
|
|
||||||
org.opencontainers.image.source=https://github.com/rosenpass/rosenpass
|
|
||||||
|
|
||||||
- name: Log in to registry
|
|
||||||
run: echo "${{ secrets.GITHUB_TOKEN }}" | docker login ghcr.io -u ${{ github.repository_owner }} --password-stdin
|
|
||||||
|
|
||||||
- name: Set up Docker Buildx
|
|
||||||
uses: docker/setup-buildx-action@v3
|
|
||||||
|
|
||||||
- name: Build and push by digest
|
|
||||||
id: build
|
|
||||||
uses: docker/build-push-action@v6
|
|
||||||
with:
|
|
||||||
context: .
|
|
||||||
file: docker/Dockerfile
|
|
||||||
push: ${{ github.event_name != 'pull_request' }}
|
|
||||||
labels: ${{ steps.meta.outputs.labels }}
|
|
||||||
tags: ghcr.io/${{ github.repository_owner }}/rp
|
|
||||||
target: rp
|
|
||||||
platforms: linux/${{ matrix.arch }}
|
|
||||||
outputs: type=image,push-by-digest=true,name-canonical=true,push=true
|
|
||||||
|
|
||||||
- name: Export digest
|
|
||||||
run: |
|
|
||||||
mkdir -p ${{ runner.temp }}/digests
|
|
||||||
digest="${{ steps.build.outputs.digest }}"
|
|
||||||
touch "${{ runner.temp }}/digests/${digest#sha256:}"
|
|
||||||
|
|
||||||
- name: Upload digest
|
|
||||||
uses: actions/upload-artifact@v4
|
|
||||||
with:
|
|
||||||
name: digests-rp-${{ matrix.arch }}
|
|
||||||
path: ${{ runner.temp }}/digests/*
|
|
||||||
if-no-files-found: error
|
|
||||||
retention-days: 1
|
|
||||||
|
|
||||||
docker-image-rosenpass:
|
|
||||||
needs:
|
|
||||||
- build-and-test-rp
|
|
||||||
# Skip if this is not a PR. Then we want to push this image.
|
|
||||||
if: ${{ github.event_name != 'pull_request' }}
|
|
||||||
# Use a matrix to build for both AMD64 and ARM64
|
|
||||||
strategy:
|
|
||||||
matrix:
|
|
||||||
arch: [amd64, arm64]
|
|
||||||
# Switch the runner based on the architecture
|
|
||||||
runs-on: ${{ matrix.arch == 'arm64' && 'ubuntu-24.04-arm' || 'ubuntu-latest' }}
|
|
||||||
steps:
|
|
||||||
- name: Checkout
|
|
||||||
uses: actions/checkout@v5
|
|
||||||
|
|
||||||
- name: Docker meta
|
|
||||||
id: meta
|
|
||||||
uses: docker/metadata-action@v5
|
|
||||||
with:
|
|
||||||
images: ghcr.io/${{ github.repository_owner }}/rosenpass
|
|
||||||
labels: |
|
|
||||||
maintainer=Karolin Varner <karo@cupdev.net>, wucke13 <wucke13@gmail.com>
|
|
||||||
org.opencontainers.image.authors=Karolin Varner <karo@cupdev.net>, wucke13 <wucke13@gmail.com>
|
|
||||||
org.opencontainers.image.title=Rosenpass
|
|
||||||
org.opencontainers.image.description=Reference implementation of the protocol rosenpass protocol
|
|
||||||
org.opencontainers.image.vendor=Rosenpass e.V.
|
|
||||||
org.opencontainers.image.licenses=MIT OR Apache-2.0
|
|
||||||
org.opencontainers.image.url=https://rosenpass.eu
|
|
||||||
org.opencontainers.image.documentation=https://rosenpass.eu/docs/
|
|
||||||
org.opencontainers.image.source=https://github.com/rosenpass/rosenpass
|
|
||||||
|
|
||||||
- name: Log in to registry
|
|
||||||
run: echo "${{ secrets.GITHUB_TOKEN }}" | docker login ghcr.io -u ${{ github.repository_owner }} --password-stdin
|
|
||||||
|
|
||||||
- name: Set up Docker Buildx
|
|
||||||
uses: docker/setup-buildx-action@v3
|
|
||||||
|
|
||||||
- name: Build and push by digest
|
|
||||||
id: build
|
|
||||||
uses: docker/build-push-action@v6
|
|
||||||
with:
|
|
||||||
context: .
|
|
||||||
file: docker/Dockerfile
|
|
||||||
push: ${{ github.event_name != 'pull_request' }}
|
|
||||||
labels: ${{ steps.meta.outputs.labels }}
|
|
||||||
tags: ghcr.io/${{ github.repository_owner }}/rosenpass
|
|
||||||
target: rosenpass
|
|
||||||
platforms: linux/${{ matrix.arch }}
|
|
||||||
outputs: type=image,push-by-digest=true,name-canonical=true,push=true
|
|
||||||
|
|
||||||
- name: Export digest
|
|
||||||
run: |
|
|
||||||
mkdir -p ${{ runner.temp }}/digests
|
|
||||||
digest="${{ steps.build.outputs.digest }}"
|
|
||||||
touch "${{ runner.temp }}/digests/${digest#sha256:}"
|
|
||||||
|
|
||||||
- name: Upload digest
|
|
||||||
uses: actions/upload-artifact@v4
|
|
||||||
with:
|
|
||||||
name: digests-rosenpass-${{ matrix.arch }}
|
|
||||||
path: ${{ runner.temp }}/digests/*
|
|
||||||
if-no-files-found: error
|
|
||||||
retention-days: 1
|
|
||||||
|
|
||||||
merge-digests:
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
needs:
|
|
||||||
- docker-image-rosenpass
|
|
||||||
- docker-image-rp
|
|
||||||
if: ${{ github.event_name != 'pull_request' }}
|
|
||||||
strategy:
|
|
||||||
matrix:
|
|
||||||
target: [rp, rosenpass]
|
|
||||||
steps:
|
|
||||||
- name: Download digests
|
|
||||||
uses: actions/download-artifact@v5
|
|
||||||
with:
|
|
||||||
path: ${{ runner.temp }}/digests
|
|
||||||
pattern: digests-${{ matrix.target }}-*
|
|
||||||
merge-multiple: true
|
|
||||||
|
|
||||||
- name: Log in to registry
|
|
||||||
run: echo "${{ secrets.GITHUB_TOKEN }}" | docker login ghcr.io -u ${{ github.repository_owner }} --password-stdin
|
|
||||||
|
|
||||||
- name: Set up Docker Buildx
|
|
||||||
uses: docker/setup-buildx-action@v3
|
|
||||||
|
|
||||||
- name: Docker meta
|
|
||||||
id: meta
|
|
||||||
uses: docker/metadata-action@v5
|
|
||||||
with:
|
|
||||||
images: ghcr.io/${{ github.repository_owner }}/${{ matrix.target }}
|
|
||||||
tags: |
|
|
||||||
type=edge,branch=main
|
|
||||||
type=sha,branch=main
|
|
||||||
type=semver,pattern={{version}}
|
|
||||||
|
|
||||||
- name: Create manifest list and push
|
|
||||||
working-directory: ${{ runner.temp }}/digests
|
|
||||||
run: |
|
|
||||||
docker buildx imagetools create $(jq -cr '.tags | map("-t " + .) | join(" ")' <<< "$DOCKER_METADATA_OUTPUT_JSON") \
|
|
||||||
$(printf 'ghcr.io/${{ github.repository_owner }}/${{ matrix.target }}@sha256:%s ' *)
|
|
||||||
|
|
||||||
- name: Inspect image
|
|
||||||
run: |
|
|
||||||
docker buildx imagetools inspect ghcr.io/${{ github.repository_owner }}/${{ matrix.target }}:${{ steps.meta.outputs.version }}
|
|
||||||
166
.github/workflows/integration.yml
vendored
@@ -1,166 +0,0 @@
|
|||||||
name: Integration Tests
|
|
||||||
|
|
||||||
on:
|
|
||||||
pull_request:
|
|
||||||
push:
|
|
||||||
branches:
|
|
||||||
- main
|
|
||||||
|
|
||||||
concurrency:
|
|
||||||
group: ${{ github.workflow }}-${{ github.ref }}
|
|
||||||
cancel-in-progress: true
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
integration-tests-x86_64-linux:
|
|
||||||
name: Integration tests x86_64-linux
|
|
||||||
runs-on:
|
|
||||||
- ubicloud-standard-2-ubuntu-2204
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v5
|
|
||||||
- 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: Extract the reference of before and after for the integration tests.
|
|
||||||
run: |
|
|
||||||
EVENT_NAME="${{ github.event_name }}"
|
|
||||||
REF_BEFORE=""
|
|
||||||
REF_AFTER="path:../../"
|
|
||||||
if [[ "$EVENT_NAME" == "pull_request" ]]; then
|
|
||||||
echo "This CI run was triggered in the context of a pull request."
|
|
||||||
REF_BEFORE="github:rosenpass/rosenpass/main"
|
|
||||||
git checkout -B pr-${{ github.event.pull_request.number }}
|
|
||||||
REF_AFTER="git+file://../../../?ref=pr-${{ github.event.pull_request.number }}"
|
|
||||||
elif [[ "$EVENT_NAME" == "push" ]]; then
|
|
||||||
echo "This CI run was triggered in the context of a push."
|
|
||||||
REF_BEFORE="github:rosenpass/rosenpass/${{ github.event.before }}"
|
|
||||||
REF_AFTER="github:rosenpass/rosenpass/${{ github.event.after }}"
|
|
||||||
else
|
|
||||||
echo "ERROR: This CI run was not triggered in the context of a pull request or a push. Exiting with error."
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
echo "REF_BEFORE=$REF_BEFORE" >> $GITHUB_ENV
|
|
||||||
echo "REF_AFTER=$REF_AFTER" >> $GITHUB_ENV
|
|
||||||
- name: Check
|
|
||||||
run: |
|
|
||||||
cd ./tests/integration
|
|
||||||
nix flake check --print-build-logs --system x86_64-linux --override-input rosenpass-old $REF_BEFORE --override-input rosenpass-new $REF_AFTER
|
|
||||||
# THE FOLLOWING TEST IS DISABLED FOR THE TIME BENG UNTIL WE GET AN ARM64 RUNNER THAT SUPPORTS KVM
|
|
||||||
#integration-tests-aarch64-linux:
|
|
||||||
# name: Integration tests aarch64-linux
|
|
||||||
# runs-on:
|
|
||||||
# - ubicloud-standard-2-arm-ubuntu-2204
|
|
||||||
# steps:
|
|
||||||
# - uses: actions/checkout@v5
|
|
||||||
# - 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: Extract the reference of before and after for the integration tests.
|
|
||||||
# run: |
|
|
||||||
# EVENT_NAME="${{ github.event_name }}"
|
|
||||||
# REF_BEFORE=""
|
|
||||||
# REF_AFTER="path:../../"
|
|
||||||
# if [[ "$EVENT_NAME" == "pull_request" ]]; then
|
|
||||||
# echo "This CI run was triggered in the context of a pull request."
|
|
||||||
# REF_BEFORE="github:rosenpass/rosenpass/main"
|
|
||||||
# #git checkout -B pr-${{ github.event.pull_request.number }}
|
|
||||||
# REF_AFTER="git+file://../../../?ref=pr-${{ github.event.pull_request.number }}"
|
|
||||||
# elif [[ "$EVENT_NAME" == "push" ]]; then
|
|
||||||
# echo "This CI run was triggered in the context of a push."
|
|
||||||
# REF_BEFORE="github:rosenpass/rosenpass/${{ github.event.before }}"
|
|
||||||
# REF_AFTER="github:rosenpass/rosenpass/${{ github.event.after }}"
|
|
||||||
# #git checkout -B ${{ github.ref_name }}
|
|
||||||
# else
|
|
||||||
# echo "ERROR: This CI run was not triggered in the context of a pull request or a push. Exiting with error."
|
|
||||||
# exit 1
|
|
||||||
# fi
|
|
||||||
# echo "REF_BEFORE=$REF_BEFORE" >> $GITHUB_ENV
|
|
||||||
# echo "REF_AFTER=$REF_AFTER" >> $GITHUB_ENV
|
|
||||||
# - name: Check
|
|
||||||
# run: |
|
|
||||||
# cd ./tests/integration
|
|
||||||
# # export QEMU_OPTS="-machine virt -cpu cortex-a57"
|
|
||||||
# nix flake check --print-build-logs --system aarch64-linux --override-input rosenpass-old $REF_BEFORE --override-input rosenpass-new $REF_AFTER
|
|
||||||
#integration-tests-i686-linux:
|
|
||||||
# name: Integration tests i686-linux
|
|
||||||
# timeout-minutes: 144000
|
|
||||||
# runs-on:
|
|
||||||
# - ubicloud-standard-8-ubuntu-2204
|
|
||||||
# steps:
|
|
||||||
# - uses: actions/checkout@v5
|
|
||||||
# - 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: Extract the reference of before and after for the integration tests.
|
|
||||||
# run: |
|
|
||||||
# EVENT_NAME="${{ github.event_name }}"
|
|
||||||
# REF_BEFORE=""
|
|
||||||
# REF_AFTER="path:../../"
|
|
||||||
# if [[ "$EVENT_NAME" == "pull_request" ]]; then
|
|
||||||
# echo "This CI run was triggered in the context of a pull request."
|
|
||||||
# REF_BEFORE="github:rosenpass/rosenpass/main"
|
|
||||||
# git checkout -B pr-${{ github.event.pull_request.number }}
|
|
||||||
# REF_AFTER="git+file://../../../?ref=pr-${{ github.event.pull_request.number }}"
|
|
||||||
# elif [[ "$EVENT_NAME" == "push" ]]; then
|
|
||||||
# echo "This CI run was triggered in the context of a push."
|
|
||||||
# REF_BEFORE="github:rosenpass/rosenpass/${{ github.event.before }}"
|
|
||||||
# REF_AFTER="github:rosenpass/rosenpass/${{ github.event.after }}"
|
|
||||||
# else
|
|
||||||
# echo "ERROR: This CI run was not triggered in the context of a pull request or a push. Exiting with error."
|
|
||||||
# exit 1
|
|
||||||
# fi
|
|
||||||
# echo "REF_BEFORE=$REF_BEFORE" >> $GITHUB_ENV
|
|
||||||
# echo "REF_AFTER=$REF_AFTER" >> $GITHUB_ENV
|
|
||||||
# - name: Check
|
|
||||||
# run: |
|
|
||||||
# cd ./tests/integration
|
|
||||||
# nix flake check --print-build-logs --system i686-linux --override-input rosenpass-old $REF_BEFORE --override-input rosenpass-new $REF_AFTER
|
|
||||||
# THE FOLLOWING TEST IS DISABLED FOR THE TIME BENG UNTIL THIS ISSUE WITH NIXOS TESTS ON DARWIN GETS RESOLVED: https://github.com/NixOS/nixpkgs/issues/294725
|
|
||||||
#integration-tests-aarch64-darwin:
|
|
||||||
# name: Integration tests aarch64-darwin
|
|
||||||
# runs-on:
|
|
||||||
# - warp-macos-13-arm64-6x
|
|
||||||
# steps:
|
|
||||||
# - uses: actions/checkout@v5
|
|
||||||
# - 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: Extract the reference of before and after for the integration tests.
|
|
||||||
# run: |
|
|
||||||
# EVENT_NAME="${{ github.event_name }}"
|
|
||||||
# REF_BEFORE=""
|
|
||||||
# REF_AFTER="path:../../"
|
|
||||||
# if [[ "$EVENT_NAME" == "pull_request" ]]; then
|
|
||||||
# echo "This CI run was triggered in the context of a pull request."
|
|
||||||
# REF_BEFORE="github:rosenpass/rosenpass/main"
|
|
||||||
# git checkout -B pr-${{ github.event.pull_request.number }}
|
|
||||||
# REF_AFTER="git+file://../../../?ref=pr-${{ github.event.pull_request.number }}"
|
|
||||||
# elif [[ "$EVENT_NAME" == "push" ]]; then
|
|
||||||
# echo "This CI run was triggered in the context of a push."
|
|
||||||
# REF_BEFORE="github:rosenpass/rosenpass/${{ github.event.before }}"
|
|
||||||
# REF_AFTER="github:rosenpass/rosenpass/${{ github.event.after }}"
|
|
||||||
# else
|
|
||||||
# echo "ERROR: This CI run was not triggered in the context of a pull request or a push. Exiting with error."
|
|
||||||
# exit 1
|
|
||||||
# fi
|
|
||||||
# echo "REF_BEFORE=$REF_BEFORE" >> $GITHUB_ENV
|
|
||||||
# echo "REF_AFTER=$REF_AFTER" >> $GITHUB_ENV
|
|
||||||
# - name: Check
|
|
||||||
# run: |
|
|
||||||
# cd ./tests/integration
|
|
||||||
# nix flake check --print-build-logs --system aarch64-darwin --override-input rosenpass-old $REF_BEFORE --override-input rosenpass-new $REF_AFTER
|
|
||||||
19
.github/workflows/manual-mac-pr.yaml
vendored
@@ -1,19 +0,0 @@
|
|||||||
name: PR Validation on Mac
|
|
||||||
on:
|
|
||||||
workflow_dispatch:
|
|
||||||
permissions:
|
|
||||||
checks: write
|
|
||||||
contents: write
|
|
||||||
concurrency:
|
|
||||||
group: manual-mac-${{ github.workflow }}-${{ github.ref }}
|
|
||||||
cancel-in-progress: true
|
|
||||||
jobs:
|
|
||||||
qc:
|
|
||||||
uses: ./.github/workflows/qc-mac.yaml
|
|
||||||
permissions:
|
|
||||||
checks: write
|
|
||||||
contents: read
|
|
||||||
nix:
|
|
||||||
uses: ./.github/workflows/nix-mac.yaml
|
|
||||||
permissions:
|
|
||||||
contents: write
|
|
||||||
114
.github/workflows/nix-mac.yaml
vendored
@@ -1,114 +0,0 @@
|
|||||||
name: Nix on Mac
|
|
||||||
permissions:
|
|
||||||
contents: write
|
|
||||||
on:
|
|
||||||
push:
|
|
||||||
branches:
|
|
||||||
- main
|
|
||||||
workflow_call:
|
|
||||||
|
|
||||||
concurrency:
|
|
||||||
group: ${{ github.workflow }}-${{ github.ref }}
|
|
||||||
cancel-in-progress: true
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
aarch64-darwin---default:
|
|
||||||
name: Build aarch64-darwin.default
|
|
||||||
runs-on:
|
|
||||||
- warp-macos-13-arm64-6x
|
|
||||||
needs:
|
|
||||||
- aarch64-darwin---rosenpass
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v5
|
|
||||||
- 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.aarch64-darwin.default --print-build-logs
|
|
||||||
aarch64-darwin---release-package:
|
|
||||||
name: Build aarch64-darwin.release-package
|
|
||||||
runs-on:
|
|
||||||
- warp-macos-13-arm64-6x
|
|
||||||
needs:
|
|
||||||
- aarch64-darwin---rosenpass
|
|
||||||
- aarch64-darwin---rp
|
|
||||||
- aarch64-darwin---rosenpass-oci-image
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v5
|
|
||||||
- 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.aarch64-darwin.release-package --print-build-logs
|
|
||||||
aarch64-darwin---rosenpass:
|
|
||||||
name: Build aarch64-darwin.rosenpass
|
|
||||||
runs-on:
|
|
||||||
- warp-macos-13-arm64-6x
|
|
||||||
needs: []
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v5
|
|
||||||
- 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.aarch64-darwin.rosenpass --print-build-logs
|
|
||||||
aarch64-darwin---rp:
|
|
||||||
name: Build aarch64-darwin.rp
|
|
||||||
runs-on:
|
|
||||||
- warp-macos-13-arm64-6x
|
|
||||||
needs: []
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v5
|
|
||||||
- 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.aarch64-darwin.rp --print-build-logs
|
|
||||||
aarch64-darwin---rosenpass-oci-image:
|
|
||||||
name: Build aarch64-darwin.rosenpass-oci-image
|
|
||||||
runs-on:
|
|
||||||
- warp-macos-13-arm64-6x
|
|
||||||
needs:
|
|
||||||
- aarch64-darwin---rosenpass
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v5
|
|
||||||
- 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.aarch64-darwin.rosenpass-oci-image --print-build-logs
|
|
||||||
aarch64-darwin---check:
|
|
||||||
name: Run Nix checks on aarch64-darwin
|
|
||||||
runs-on:
|
|
||||||
- warp-macos-13-arm64-6x
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v5
|
|
||||||
- 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
|
|
||||||
189
.github/workflows/nix.yaml
vendored
@@ -15,11 +15,11 @@ jobs:
|
|||||||
i686-linux---default:
|
i686-linux---default:
|
||||||
name: Build i686-linux.default
|
name: Build i686-linux.default
|
||||||
runs-on:
|
runs-on:
|
||||||
- ubicloud-standard-2-ubuntu-2204
|
- ubuntu-latest
|
||||||
needs:
|
needs:
|
||||||
- i686-linux---rosenpass
|
- i686-linux---rosenpass
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v5
|
- uses: actions/checkout@v4
|
||||||
- uses: cachix/install-nix-action@v30
|
- uses: cachix/install-nix-action@v30
|
||||||
with:
|
with:
|
||||||
nix_path: nixpkgs=channel:nixos-unstable
|
nix_path: nixpkgs=channel:nixos-unstable
|
||||||
@@ -32,10 +32,10 @@ jobs:
|
|||||||
i686-linux---rosenpass:
|
i686-linux---rosenpass:
|
||||||
name: Build i686-linux.rosenpass
|
name: Build i686-linux.rosenpass
|
||||||
runs-on:
|
runs-on:
|
||||||
- ubicloud-standard-2-ubuntu-2204
|
- ubuntu-latest
|
||||||
needs: []
|
needs: []
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v5
|
- uses: actions/checkout@v4
|
||||||
- uses: cachix/install-nix-action@v30
|
- uses: cachix/install-nix-action@v30
|
||||||
with:
|
with:
|
||||||
nix_path: nixpkgs=channel:nixos-unstable
|
nix_path: nixpkgs=channel:nixos-unstable
|
||||||
@@ -48,11 +48,11 @@ jobs:
|
|||||||
i686-linux---rosenpass-oci-image:
|
i686-linux---rosenpass-oci-image:
|
||||||
name: Build i686-linux.rosenpass-oci-image
|
name: Build i686-linux.rosenpass-oci-image
|
||||||
runs-on:
|
runs-on:
|
||||||
- ubicloud-standard-2-ubuntu-2204
|
- ubuntu-latest
|
||||||
needs:
|
needs:
|
||||||
- i686-linux---rosenpass
|
- i686-linux---rosenpass
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v5
|
- uses: actions/checkout@v4
|
||||||
- uses: cachix/install-nix-action@v30
|
- uses: cachix/install-nix-action@v30
|
||||||
with:
|
with:
|
||||||
nix_path: nixpkgs=channel:nixos-unstable
|
nix_path: nixpkgs=channel:nixos-unstable
|
||||||
@@ -65,9 +65,9 @@ jobs:
|
|||||||
i686-linux---check:
|
i686-linux---check:
|
||||||
name: Run Nix checks on i686-linux
|
name: Run Nix checks on i686-linux
|
||||||
runs-on:
|
runs-on:
|
||||||
- ubicloud-standard-2-ubuntu-2204
|
- ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v5
|
- uses: actions/checkout@v4
|
||||||
- uses: cachix/install-nix-action@v30
|
- uses: cachix/install-nix-action@v30
|
||||||
with:
|
with:
|
||||||
nix_path: nixpkgs=channel:nixos-unstable
|
nix_path: nixpkgs=channel:nixos-unstable
|
||||||
@@ -76,16 +76,115 @@ jobs:
|
|||||||
name: rosenpass
|
name: rosenpass
|
||||||
authToken: ${{ secrets.CACHIX_AUTH_TOKEN }}
|
authToken: ${{ secrets.CACHIX_AUTH_TOKEN }}
|
||||||
- name: Check
|
- name: Check
|
||||||
run: |
|
run: nix flake check . --print-build-logs
|
||||||
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:
|
x86_64-linux---default:
|
||||||
name: Build x86_64-linux.default
|
name: Build x86_64-linux.default
|
||||||
runs-on:
|
runs-on:
|
||||||
- ubicloud-standard-2-ubuntu-2204
|
- ubuntu-latest
|
||||||
needs:
|
needs:
|
||||||
- x86_64-linux---rosenpass
|
- x86_64-linux---rosenpass
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v5
|
- uses: actions/checkout@v4
|
||||||
- uses: cachix/install-nix-action@v30
|
- uses: cachix/install-nix-action@v30
|
||||||
with:
|
with:
|
||||||
nix_path: nixpkgs=channel:nixos-unstable
|
nix_path: nixpkgs=channel:nixos-unstable
|
||||||
@@ -98,11 +197,11 @@ jobs:
|
|||||||
x86_64-linux---proof-proverif:
|
x86_64-linux---proof-proverif:
|
||||||
name: Build x86_64-linux.proof-proverif
|
name: Build x86_64-linux.proof-proverif
|
||||||
runs-on:
|
runs-on:
|
||||||
- ubicloud-standard-2-ubuntu-2204
|
- ubuntu-latest
|
||||||
needs:
|
needs:
|
||||||
- x86_64-linux---proverif-patched
|
- x86_64-linux---proverif-patched
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v5
|
- uses: actions/checkout@v4
|
||||||
- uses: cachix/install-nix-action@v30
|
- uses: cachix/install-nix-action@v30
|
||||||
with:
|
with:
|
||||||
nix_path: nixpkgs=channel:nixos-unstable
|
nix_path: nixpkgs=channel:nixos-unstable
|
||||||
@@ -115,10 +214,10 @@ jobs:
|
|||||||
x86_64-linux---proverif-patched:
|
x86_64-linux---proverif-patched:
|
||||||
name: Build x86_64-linux.proverif-patched
|
name: Build x86_64-linux.proverif-patched
|
||||||
runs-on:
|
runs-on:
|
||||||
- ubicloud-standard-2-ubuntu-2204
|
- ubuntu-latest
|
||||||
needs: []
|
needs: []
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v5
|
- uses: actions/checkout@v4
|
||||||
- uses: cachix/install-nix-action@v30
|
- uses: cachix/install-nix-action@v30
|
||||||
with:
|
with:
|
||||||
nix_path: nixpkgs=channel:nixos-unstable
|
nix_path: nixpkgs=channel:nixos-unstable
|
||||||
@@ -131,13 +230,13 @@ jobs:
|
|||||||
x86_64-linux---release-package:
|
x86_64-linux---release-package:
|
||||||
name: Build x86_64-linux.release-package
|
name: Build x86_64-linux.release-package
|
||||||
runs-on:
|
runs-on:
|
||||||
- ubicloud-standard-2-ubuntu-2204
|
- ubuntu-latest
|
||||||
needs:
|
needs:
|
||||||
- x86_64-linux---rosenpass-static
|
- x86_64-linux---rosenpass-static
|
||||||
- x86_64-linux---rosenpass-static-oci-image
|
- x86_64-linux---rosenpass-static-oci-image
|
||||||
- x86_64-linux---rp-static
|
- x86_64-linux---rp-static
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v5
|
- uses: actions/checkout@v4
|
||||||
- uses: cachix/install-nix-action@v30
|
- uses: cachix/install-nix-action@v30
|
||||||
with:
|
with:
|
||||||
nix_path: nixpkgs=channel:nixos-unstable
|
nix_path: nixpkgs=channel:nixos-unstable
|
||||||
@@ -150,7 +249,7 @@ jobs:
|
|||||||
# aarch64-linux---release-package:
|
# aarch64-linux---release-package:
|
||||||
# name: Build aarch64-linux.release-package
|
# name: Build aarch64-linux.release-package
|
||||||
# runs-on:
|
# runs-on:
|
||||||
# - ubicloud-standard-2-arm-ubuntu-2204
|
# - ubuntu-latest
|
||||||
# needs:
|
# needs:
|
||||||
# - aarch64-linux---rosenpass-oci-image
|
# - aarch64-linux---rosenpass-oci-image
|
||||||
# - aarch64-linux---rosenpass
|
# - aarch64-linux---rosenpass
|
||||||
@@ -159,7 +258,7 @@ jobs:
|
|||||||
# - run: |
|
# - run: |
|
||||||
# DEBIAN_FRONTEND=noninteractive
|
# 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
|
# 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@v5
|
# - uses: actions/checkout@v4
|
||||||
# - uses: cachix/install-nix-action@v30
|
# - uses: cachix/install-nix-action@v30
|
||||||
# with:
|
# with:
|
||||||
# nix_path: nixpkgs=channel:nixos-unstable
|
# nix_path: nixpkgs=channel:nixos-unstable
|
||||||
@@ -174,10 +273,10 @@ jobs:
|
|||||||
x86_64-linux---rosenpass:
|
x86_64-linux---rosenpass:
|
||||||
name: Build x86_64-linux.rosenpass
|
name: Build x86_64-linux.rosenpass
|
||||||
runs-on:
|
runs-on:
|
||||||
- ubicloud-standard-2-ubuntu-2204
|
- ubuntu-latest
|
||||||
needs: []
|
needs: []
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v5
|
- uses: actions/checkout@v4
|
||||||
- uses: cachix/install-nix-action@v30
|
- uses: cachix/install-nix-action@v30
|
||||||
with:
|
with:
|
||||||
nix_path: nixpkgs=channel:nixos-unstable
|
nix_path: nixpkgs=channel:nixos-unstable
|
||||||
@@ -190,13 +289,13 @@ jobs:
|
|||||||
aarch64-linux---rosenpass:
|
aarch64-linux---rosenpass:
|
||||||
name: Build aarch64-linux.rosenpass
|
name: Build aarch64-linux.rosenpass
|
||||||
runs-on:
|
runs-on:
|
||||||
- ubicloud-standard-2-arm-ubuntu-2204
|
- ubuntu-latest
|
||||||
needs: []
|
needs: []
|
||||||
steps:
|
steps:
|
||||||
- run: |
|
- run: |
|
||||||
DEBIAN_FRONTEND=noninteractive
|
DEBIAN_FRONTEND=noninteractive
|
||||||
sudo apt-get update -q -y && sudo apt-get install -q -y qemu-system-aarch64 qemu-efi-aarch64 binfmt-support qemu-user-static
|
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@v5
|
- uses: actions/checkout@v4
|
||||||
- uses: cachix/install-nix-action@v30
|
- uses: cachix/install-nix-action@v30
|
||||||
with:
|
with:
|
||||||
nix_path: nixpkgs=channel:nixos-unstable
|
nix_path: nixpkgs=channel:nixos-unstable
|
||||||
@@ -211,13 +310,13 @@ jobs:
|
|||||||
aarch64-linux---rp:
|
aarch64-linux---rp:
|
||||||
name: Build aarch64-linux.rp
|
name: Build aarch64-linux.rp
|
||||||
runs-on:
|
runs-on:
|
||||||
- ubicloud-standard-2-arm-ubuntu-2204
|
- ubuntu-latest
|
||||||
needs: []
|
needs: []
|
||||||
steps:
|
steps:
|
||||||
- run: |
|
- run: |
|
||||||
DEBIAN_FRONTEND=noninteractive
|
DEBIAN_FRONTEND=noninteractive
|
||||||
sudo apt-get update -q -y && sudo apt-get install -q -y qemu-system-aarch64 qemu-efi-aarch64 binfmt-support qemu-user-static
|
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@v5
|
- uses: actions/checkout@v4
|
||||||
- uses: cachix/install-nix-action@v30
|
- uses: cachix/install-nix-action@v30
|
||||||
with:
|
with:
|
||||||
nix_path: nixpkgs=channel:nixos-unstable
|
nix_path: nixpkgs=channel:nixos-unstable
|
||||||
@@ -232,11 +331,11 @@ jobs:
|
|||||||
x86_64-linux---rosenpass-oci-image:
|
x86_64-linux---rosenpass-oci-image:
|
||||||
name: Build x86_64-linux.rosenpass-oci-image
|
name: Build x86_64-linux.rosenpass-oci-image
|
||||||
runs-on:
|
runs-on:
|
||||||
- ubicloud-standard-2-ubuntu-2204
|
- ubuntu-latest
|
||||||
needs:
|
needs:
|
||||||
- x86_64-linux---rosenpass
|
- x86_64-linux---rosenpass
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v5
|
- uses: actions/checkout@v4
|
||||||
- uses: cachix/install-nix-action@v30
|
- uses: cachix/install-nix-action@v30
|
||||||
with:
|
with:
|
||||||
nix_path: nixpkgs=channel:nixos-unstable
|
nix_path: nixpkgs=channel:nixos-unstable
|
||||||
@@ -249,14 +348,14 @@ jobs:
|
|||||||
aarch64-linux---rosenpass-oci-image:
|
aarch64-linux---rosenpass-oci-image:
|
||||||
name: Build aarch64-linux.rosenpass-oci-image
|
name: Build aarch64-linux.rosenpass-oci-image
|
||||||
runs-on:
|
runs-on:
|
||||||
- ubicloud-standard-2-arm-ubuntu-2204
|
- ubuntu-latest
|
||||||
needs:
|
needs:
|
||||||
- aarch64-linux---rosenpass
|
- aarch64-linux---rosenpass
|
||||||
steps:
|
steps:
|
||||||
- run: |
|
- run: |
|
||||||
DEBIAN_FRONTEND=noninteractive
|
DEBIAN_FRONTEND=noninteractive
|
||||||
sudo apt-get update -q -y && sudo apt-get install -q -y qemu-system-aarch64 qemu-efi-aarch64 binfmt-support qemu-user-static
|
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@v5
|
- uses: actions/checkout@v4
|
||||||
- uses: cachix/install-nix-action@v30
|
- uses: cachix/install-nix-action@v30
|
||||||
with:
|
with:
|
||||||
nix_path: nixpkgs=channel:nixos-unstable
|
nix_path: nixpkgs=channel:nixos-unstable
|
||||||
@@ -271,10 +370,10 @@ jobs:
|
|||||||
x86_64-linux---rosenpass-static:
|
x86_64-linux---rosenpass-static:
|
||||||
name: Build x86_64-linux.rosenpass-static
|
name: Build x86_64-linux.rosenpass-static
|
||||||
runs-on:
|
runs-on:
|
||||||
- ubicloud-standard-2-ubuntu-2204
|
- ubuntu-latest
|
||||||
needs: []
|
needs: []
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v5
|
- uses: actions/checkout@v4
|
||||||
- uses: cachix/install-nix-action@v30
|
- uses: cachix/install-nix-action@v30
|
||||||
with:
|
with:
|
||||||
nix_path: nixpkgs=channel:nixos-unstable
|
nix_path: nixpkgs=channel:nixos-unstable
|
||||||
@@ -287,10 +386,10 @@ jobs:
|
|||||||
x86_64-linux---rp-static:
|
x86_64-linux---rp-static:
|
||||||
name: Build x86_64-linux.rp-static
|
name: Build x86_64-linux.rp-static
|
||||||
runs-on:
|
runs-on:
|
||||||
- ubicloud-standard-2-ubuntu-2204
|
- ubuntu-latest
|
||||||
needs: []
|
needs: []
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v5
|
- uses: actions/checkout@v4
|
||||||
- uses: cachix/install-nix-action@v30
|
- uses: cachix/install-nix-action@v30
|
||||||
with:
|
with:
|
||||||
nix_path: nixpkgs=channel:nixos-unstable
|
nix_path: nixpkgs=channel:nixos-unstable
|
||||||
@@ -303,11 +402,11 @@ jobs:
|
|||||||
x86_64-linux---rosenpass-static-oci-image:
|
x86_64-linux---rosenpass-static-oci-image:
|
||||||
name: Build x86_64-linux.rosenpass-static-oci-image
|
name: Build x86_64-linux.rosenpass-static-oci-image
|
||||||
runs-on:
|
runs-on:
|
||||||
- ubicloud-standard-2-ubuntu-2204
|
- ubuntu-latest
|
||||||
needs:
|
needs:
|
||||||
- x86_64-linux---rosenpass-static
|
- x86_64-linux---rosenpass-static
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v5
|
- uses: actions/checkout@v4
|
||||||
- uses: cachix/install-nix-action@v30
|
- uses: cachix/install-nix-action@v30
|
||||||
with:
|
with:
|
||||||
nix_path: nixpkgs=channel:nixos-unstable
|
nix_path: nixpkgs=channel:nixos-unstable
|
||||||
@@ -320,10 +419,10 @@ jobs:
|
|||||||
x86_64-linux---whitepaper:
|
x86_64-linux---whitepaper:
|
||||||
name: Build x86_64-linux.whitepaper
|
name: Build x86_64-linux.whitepaper
|
||||||
runs-on:
|
runs-on:
|
||||||
- ubicloud-standard-2-ubuntu-2204
|
- ubuntu-latest
|
||||||
needs: []
|
needs: []
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v5
|
- uses: actions/checkout@v4
|
||||||
- uses: cachix/install-nix-action@v30
|
- uses: cachix/install-nix-action@v30
|
||||||
with:
|
with:
|
||||||
nix_path: nixpkgs=channel:nixos-unstable
|
nix_path: nixpkgs=channel:nixos-unstable
|
||||||
@@ -336,9 +435,9 @@ jobs:
|
|||||||
x86_64-linux---check:
|
x86_64-linux---check:
|
||||||
name: Run Nix checks on x86_64-linux
|
name: Run Nix checks on x86_64-linux
|
||||||
runs-on:
|
runs-on:
|
||||||
- ubicloud-standard-2-ubuntu-2204
|
- ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v5
|
- uses: actions/checkout@v4
|
||||||
- uses: cachix/install-nix-action@v30
|
- uses: cachix/install-nix-action@v30
|
||||||
with:
|
with:
|
||||||
nix_path: nixpkgs=channel:nixos-unstable
|
nix_path: nixpkgs=channel:nixos-unstable
|
||||||
@@ -350,10 +449,10 @@ jobs:
|
|||||||
run: nix flake check . --print-build-logs
|
run: nix flake check . --print-build-logs
|
||||||
x86_64-linux---whitepaper-upload:
|
x86_64-linux---whitepaper-upload:
|
||||||
name: Upload whitepaper x86_64-linux
|
name: Upload whitepaper x86_64-linux
|
||||||
runs-on: ubicloud-standard-2-ubuntu-2204
|
runs-on: ubuntu-latest
|
||||||
if: ${{ github.ref == 'refs/heads/main' }}
|
if: ${{ github.ref == 'refs/heads/main' }}
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v5
|
- uses: actions/checkout@v4
|
||||||
- uses: cachix/install-nix-action@v30
|
- uses: cachix/install-nix-action@v30
|
||||||
with:
|
with:
|
||||||
nix_path: nixpkgs=channel:nixos-unstable
|
nix_path: nixpkgs=channel:nixos-unstable
|
||||||
|
|||||||
32
.github/workflows/qc-mac.yaml
vendored
@@ -1,32 +0,0 @@
|
|||||||
name: QC Mac
|
|
||||||
on:
|
|
||||||
push:
|
|
||||||
branches: [main]
|
|
||||||
workflow_call:
|
|
||||||
|
|
||||||
concurrency:
|
|
||||||
group: ${{ github.workflow }}-${{ github.ref }}
|
|
||||||
cancel-in-progress: true
|
|
||||||
|
|
||||||
permissions:
|
|
||||||
checks: write
|
|
||||||
contents: read
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
cargo-test-mac:
|
|
||||||
runs-on: warp-macos-13-arm64-6x
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v5
|
|
||||||
- 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
|
|
||||||
100
.github/workflows/qc.yaml
vendored
@@ -14,49 +14,33 @@ permissions:
|
|||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
prettier:
|
prettier:
|
||||||
runs-on: ubicloud-standard-2-ubuntu-2204
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v5
|
- uses: actions/checkout@v4
|
||||||
- uses: actionsx/prettier@v3
|
- uses: actionsx/prettier@v3
|
||||||
with:
|
with:
|
||||||
args: --check .
|
args: --check .
|
||||||
|
|
||||||
shellcheck:
|
shellcheck:
|
||||||
name: Shellcheck
|
name: Shellcheck
|
||||||
runs-on: ubicloud-standard-2-ubuntu-2204
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v5
|
- uses: actions/checkout@v4
|
||||||
- name: Run ShellCheck
|
- name: Run ShellCheck
|
||||||
uses: ludeeus/action-shellcheck@master
|
uses: ludeeus/action-shellcheck@master
|
||||||
|
|
||||||
rustfmt:
|
rustfmt:
|
||||||
name: Rust code formatting
|
name: Rust Format
|
||||||
runs-on: ubicloud-standard-2-ubuntu-2204
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v5
|
- uses: actions/checkout@v4
|
||||||
- uses: actions/cache@v4
|
- name: Run Rust Formatting Script
|
||||||
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 override set nightly
|
|
||||||
- run: rustup component add rustfmt
|
|
||||||
- name: Run Cargo Fmt
|
|
||||||
run: cargo fmt --all --check
|
|
||||||
- name: Run Rust Markdown code block Formatting Script
|
|
||||||
run: bash format_rust_code.sh --mode check
|
run: bash format_rust_code.sh --mode check
|
||||||
|
|
||||||
cargo-bench:
|
cargo-bench:
|
||||||
runs-on: ubicloud-standard-2-ubuntu-2204
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v5
|
- uses: actions/checkout@v4
|
||||||
- uses: actions/cache@v4
|
- uses: actions/cache@v4
|
||||||
with:
|
with:
|
||||||
path: |
|
path: |
|
||||||
@@ -73,26 +57,26 @@ jobs:
|
|||||||
|
|
||||||
mandoc:
|
mandoc:
|
||||||
name: mandoc
|
name: mandoc
|
||||||
runs-on: ubicloud-standard-2-ubuntu-2204
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- name: Install mandoc
|
- name: Install mandoc
|
||||||
run: sudo apt-get install -y mandoc
|
run: sudo apt-get install -y mandoc
|
||||||
- uses: actions/checkout@v5
|
- uses: actions/checkout@v4
|
||||||
- name: Check rp.1
|
- name: Check rp.1
|
||||||
run: doc/check.sh doc/rp.1
|
run: doc/check.sh doc/rp.1
|
||||||
|
|
||||||
cargo-audit:
|
cargo-audit:
|
||||||
runs-on: ubicloud-standard-2-ubuntu-2204
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v5
|
- uses: actions/checkout@v4
|
||||||
- uses: actions-rs/audit-check@v1
|
- uses: actions-rs/audit-check@v1
|
||||||
with:
|
with:
|
||||||
token: ${{ secrets.GITHUB_TOKEN }}
|
token: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
|
||||||
cargo-clippy:
|
cargo-clippy:
|
||||||
runs-on: ubicloud-standard-2-ubuntu-2204
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v5
|
- uses: actions/checkout@v4
|
||||||
- uses: actions/cache@v4
|
- uses: actions/cache@v4
|
||||||
with:
|
with:
|
||||||
path: |
|
path: |
|
||||||
@@ -109,9 +93,9 @@ jobs:
|
|||||||
args: --all-features
|
args: --all-features
|
||||||
|
|
||||||
cargo-doc:
|
cargo-doc:
|
||||||
runs-on: ubicloud-standard-2-ubuntu-2204
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v5
|
- uses: actions/checkout@v4
|
||||||
- uses: actions/cache@v4
|
- uses: actions/cache@v4
|
||||||
with:
|
with:
|
||||||
path: |
|
path: |
|
||||||
@@ -128,9 +112,14 @@ jobs:
|
|||||||
- run: RUSTDOCFLAGS="-D warnings" cargo doc --no-deps --document-private-items
|
- run: RUSTDOCFLAGS="-D warnings" cargo doc --no-deps --document-private-items
|
||||||
|
|
||||||
cargo-test:
|
cargo-test:
|
||||||
runs-on: ubicloud-standard-2-ubuntu-2204
|
runs-on: ${{ matrix.os }}
|
||||||
|
strategy:
|
||||||
|
matrix:
|
||||||
|
os: [ubuntu-latest, macos-13]
|
||||||
|
# - ubuntu is x86-64
|
||||||
|
# - macos-13 is also x86-64 architecture
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v5
|
- uses: actions/checkout@v4
|
||||||
- uses: actions/cache@v4
|
- uses: actions/cache@v4
|
||||||
with:
|
with:
|
||||||
path: |
|
path: |
|
||||||
@@ -147,9 +136,9 @@ jobs:
|
|||||||
|
|
||||||
cargo-test-nix-devshell-x86_64-linux:
|
cargo-test-nix-devshell-x86_64-linux:
|
||||||
runs-on:
|
runs-on:
|
||||||
- ubicloud-standard-2-ubuntu-2204
|
- ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v5
|
- uses: actions/checkout@v4
|
||||||
- uses: actions/cache@v4
|
- uses: actions/cache@v4
|
||||||
with:
|
with:
|
||||||
path: |
|
path: |
|
||||||
@@ -169,9 +158,9 @@ jobs:
|
|||||||
- run: nix develop --command cargo test --workspace --all-features
|
- run: nix develop --command cargo test --workspace --all-features
|
||||||
|
|
||||||
cargo-fuzz:
|
cargo-fuzz:
|
||||||
runs-on: ubicloud-standard-2-ubuntu-2204
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v5
|
- uses: actions/checkout@v4
|
||||||
- uses: actions/cache@v4
|
- uses: actions/cache@v4
|
||||||
with:
|
with:
|
||||||
path: |
|
path: |
|
||||||
@@ -184,7 +173,7 @@ jobs:
|
|||||||
- name: Install nightly toolchain
|
- name: Install nightly toolchain
|
||||||
run: |
|
run: |
|
||||||
rustup toolchain install nightly
|
rustup toolchain install nightly
|
||||||
rustup override set nightly
|
rustup default nightly
|
||||||
- name: Install cargo-fuzz
|
- name: Install cargo-fuzz
|
||||||
run: cargo install cargo-fuzz
|
run: cargo install cargo-fuzz
|
||||||
- name: Run fuzzing
|
- name: Run fuzzing
|
||||||
@@ -202,35 +191,22 @@ jobs:
|
|||||||
cargo fuzz run fuzz_vec_secret_alloc_memfdsec_mallocfb -- -max_total_time=5
|
cargo fuzz run fuzz_vec_secret_alloc_memfdsec_mallocfb -- -max_total_time=5
|
||||||
|
|
||||||
codecov:
|
codecov:
|
||||||
runs-on: ubicloud-standard-2-ubuntu-2204
|
runs-on: ubuntu-latest
|
||||||
env:
|
|
||||||
RUSTUP_TOOLCHAIN: nightly
|
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v5
|
- 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 override set nightly
|
|
||||||
- run: rustup component add llvm-tools-preview
|
- run: rustup component add llvm-tools-preview
|
||||||
- run: |
|
- run: |
|
||||||
cargo install cargo-llvm-cov || true
|
cargo install cargo-llvm-cov || true
|
||||||
cargo install grcov || true
|
cargo llvm-cov \
|
||||||
./coverage_report.sh
|
--workspace\
|
||||||
|
--all-features \
|
||||||
|
--lcov \
|
||||||
|
--output-path coverage.lcov
|
||||||
# If using tarapulin
|
# If using tarapulin
|
||||||
#- run: cargo install cargo-tarpaulin
|
#- run: cargo install cargo-tarpaulin
|
||||||
#- run: cargo tarpaulin --out Xml
|
#- run: cargo tarpaulin --out Xml
|
||||||
- name: Upload coverage reports to Codecov
|
- name: Upload coverage reports to Codecov
|
||||||
uses: codecov/codecov-action@v5
|
uses: codecov/codecov-action@v5
|
||||||
with:
|
with:
|
||||||
files: ./target/grcov/lcov
|
files: ./coverage.lcov
|
||||||
verbose: true
|
verbose: true
|
||||||
CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }}
|
|
||||||
|
|||||||
8
.github/workflows/regressions.yml
vendored
@@ -14,9 +14,9 @@ permissions:
|
|||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
multi-peer:
|
multi-peer:
|
||||||
runs-on: ubicloud-standard-2-ubuntu-2204
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v5
|
- uses: actions/checkout@v4
|
||||||
- run: cargo build --bin rosenpass --release
|
- run: cargo build --bin rosenpass --release
|
||||||
- run: python misc/generate_configs.py
|
- run: python misc/generate_configs.py
|
||||||
- run: chmod +x .ci/run-regression.sh
|
- run: chmod +x .ci/run-regression.sh
|
||||||
@@ -25,9 +25,9 @@ jobs:
|
|||||||
[ $(ls -1 output/ate/out | wc -l) -eq 100 ]
|
[ $(ls -1 output/ate/out | wc -l) -eq 100 ]
|
||||||
|
|
||||||
boot-race:
|
boot-race:
|
||||||
runs-on: ubicloud-standard-2-ubuntu-2204
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v5
|
- uses: actions/checkout@v4
|
||||||
- run: cargo build --bin rosenpass --release
|
- run: cargo build --bin rosenpass --release
|
||||||
- run: chmod +x .ci/boot_race/run.sh
|
- 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/a.toml
|
||||||
|
|||||||
31
.github/workflows/release.yaml
vendored
@@ -11,8 +11,10 @@ jobs:
|
|||||||
runs-on:
|
runs-on:
|
||||||
- ubuntu-latest
|
- ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v5
|
- uses: actions/checkout@v4
|
||||||
- uses: cachix/install-nix-action@v30
|
- uses: cachix/install-nix-action@v30
|
||||||
|
with:
|
||||||
|
nix_path: nixpkgs=channel:nixos-unstable
|
||||||
- uses: cachix/cachix-action@v15
|
- uses: cachix/cachix-action@v15
|
||||||
with:
|
with:
|
||||||
name: rosenpass
|
name: rosenpass
|
||||||
@@ -30,8 +32,10 @@ jobs:
|
|||||||
runs-on:
|
runs-on:
|
||||||
- macos-13
|
- macos-13
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v5
|
- uses: actions/checkout@v4
|
||||||
- uses: cachix/install-nix-action@v30
|
- uses: cachix/install-nix-action@v30
|
||||||
|
with:
|
||||||
|
nix_path: nixpkgs=channel:nixos-unstable
|
||||||
- uses: cachix/cachix-action@v15
|
- uses: cachix/cachix-action@v15
|
||||||
with:
|
with:
|
||||||
name: rosenpass
|
name: rosenpass
|
||||||
@@ -49,7 +53,7 @@ jobs:
|
|||||||
runs-on:
|
runs-on:
|
||||||
- ubuntu-latest
|
- ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v5
|
- uses: actions/checkout@v4
|
||||||
- uses: cachix/install-nix-action@v30
|
- uses: cachix/install-nix-action@v30
|
||||||
with:
|
with:
|
||||||
nix_path: nixpkgs=channel:nixos-unstable
|
nix_path: nixpkgs=channel:nixos-unstable
|
||||||
@@ -65,24 +69,3 @@ jobs:
|
|||||||
draft: ${{ contains(github.ref_name, 'rc') }}
|
draft: ${{ contains(github.ref_name, 'rc') }}
|
||||||
prerelease: ${{ contains(github.ref_name, 'alpha') || contains(github.ref_name, 'beta') }}
|
prerelease: ${{ contains(github.ref_name, 'alpha') || contains(github.ref_name, 'beta') }}
|
||||||
files: result/*
|
files: result/*
|
||||||
linux-packages:
|
|
||||||
name: Build and upload DEB and RPM packages
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v5
|
|
||||||
- uses: cachix/install-nix-action@v30
|
|
||||||
- uses: cachix/cachix-action@v15
|
|
||||||
with:
|
|
||||||
name: rosenpass
|
|
||||||
authToken: ${{ secrets.CACHIX_AUTH_TOKEN }}
|
|
||||||
- name: Build DEB & RPM package
|
|
||||||
run: |
|
|
||||||
mkdir packages
|
|
||||||
for f in $(nix build .#package-deb .#package-rpm --print-out-paths); do cp "$f" "packages/${f#*-}"; done
|
|
||||||
- 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: |
|
|
||||||
packages/*
|
|
||||||
|
|||||||
177
.github/workflows/supply-chain.yml
vendored
@@ -1,177 +0,0 @@
|
|||||||
name: Supply-Chain
|
|
||||||
on:
|
|
||||||
pull_request:
|
|
||||||
push:
|
|
||||||
branches: [main]
|
|
||||||
|
|
||||||
concurrency:
|
|
||||||
group: ${{ github.workflow }}-${{ github.ref }}
|
|
||||||
cancel-in-progress: true
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
cargo-deny:
|
|
||||||
name: Deny dependencies with vulnerabilities or incompatible licenses
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v5
|
|
||||||
- uses: EmbarkStudios/cargo-deny-action@v2
|
|
||||||
cargo-supply-chain:
|
|
||||||
name: Supply Chain Report
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v5
|
|
||||||
- uses: actions/cache@v4
|
|
||||||
with:
|
|
||||||
path: |
|
|
||||||
~/.cargo/bin/
|
|
||||||
~/.cargo/registry/index/
|
|
||||||
~/.cargo/registry/cache/
|
|
||||||
~/.cache/cargo-supply-chain/
|
|
||||||
key: cargo-supply-chain-cache
|
|
||||||
- name: Install nightly toolchain
|
|
||||||
run: |
|
|
||||||
rustup toolchain install nightly
|
|
||||||
rustup override set nightly
|
|
||||||
- uses: actions/cache@v4
|
|
||||||
with:
|
|
||||||
path: ${{ runner.tool_cache }}/cargo-supply-chain
|
|
||||||
key: cargo-supply-chain-bin
|
|
||||||
- name: Add the tool cache directory to the search path
|
|
||||||
run: echo "${{ runner.tool_cache }}/cargo-supply-chain/bin" >> $GITHUB_PATH
|
|
||||||
- name: Ensure that the tool cache is populated with the cargo-supply-chain binary
|
|
||||||
run: cargo install --root ${{ runner.tool_cache }}/cargo-supply-chain cargo-supply-chain
|
|
||||||
- name: Update data for cargo-supply-chain
|
|
||||||
run: cargo supply-chain update
|
|
||||||
- name: Generate cargo-supply-chain report about publishers
|
|
||||||
run: cargo supply-chain publishers
|
|
||||||
- name: Generate cargo-supply-chain report about crates
|
|
||||||
run: cargo supply-chain crates
|
|
||||||
# The setup for cargo-vet follows the recommendations in the cargo-vet documentation: https://mozilla.github.io/cargo-vet/configuring-ci.html
|
|
||||||
cargo-vet:
|
|
||||||
name: Vet Dependencies
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
permissions:
|
|
||||||
contents: write
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v5
|
|
||||||
with:
|
|
||||||
token: ${{ secrets.GITHUB_TOKEN }}
|
|
||||||
- uses: actions/cache@v4
|
|
||||||
with:
|
|
||||||
path: |
|
|
||||||
~/.cargo/bin/
|
|
||||||
~/.cargo/registry/index/
|
|
||||||
~/.cargo/registry/cache/
|
|
||||||
key: cargo-vet-cache
|
|
||||||
- name: Install nightly toolchain
|
|
||||||
run: |
|
|
||||||
rustup toolchain install nightly
|
|
||||||
rustup override set nightly
|
|
||||||
- uses: actions/cache@v4
|
|
||||||
with:
|
|
||||||
path: ${{ runner.tool_cache }}/cargo-vet
|
|
||||||
key: cargo-vet-bin
|
|
||||||
- name: Add the tool cache directory to the search path
|
|
||||||
run: echo "${{ runner.tool_cache }}/cargo-vet/bin" >> $GITHUB_PATH
|
|
||||||
- name: Ensure that the tool cache is populated with the cargo-vet binary
|
|
||||||
run: cargo install --root ${{ runner.tool_cache }}/cargo-vet cargo-vet
|
|
||||||
- name: Check which event triggered this CI run, a push or a pull request.
|
|
||||||
run: |
|
|
||||||
EVENT_NAME="${{ github.event_name }}"
|
|
||||||
IS_PR="false"
|
|
||||||
IS_PUSH="false"
|
|
||||||
if [[ "$EVENT_NAME" == "pull_request" ]]; then
|
|
||||||
echo "This CI run was triggered in the context of a pull request."
|
|
||||||
IS_PR="true"
|
|
||||||
elif [[ "$EVENT_NAME" == "push" ]]; then
|
|
||||||
echo "This CI run was triggered in the context of a push."
|
|
||||||
IS_PUSH="true"
|
|
||||||
else
|
|
||||||
echo "ERROR: This CI run was not triggered in the context of a pull request or a push. Exiting with error."
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
echo "IS_PR=$IS_PR" >> $GITHUB_ENV
|
|
||||||
echo "IS_PUSH=$IS_PUSH" >> $GITHUB_ENV
|
|
||||||
shell: bash
|
|
||||||
- name: Check if last commit was by Dependabot
|
|
||||||
run: |
|
|
||||||
# Depending on the trigger for, the relevant commit has to be deduced differently.
|
|
||||||
if [[ "$IS_PR" == true ]]; then
|
|
||||||
# This is the commit ID for the last commit to the head branch of the pull request.
|
|
||||||
# If we used github.sha here instead, it would point to a merge commit between the PR and the main branch, which is only created for the CI run.
|
|
||||||
SHA="${{ github.event.pull_request.head.sha }}"
|
|
||||||
REF="${{ github.head_ref }}"
|
|
||||||
elif [[ "$IS_PUSH" == "true" ]]; then
|
|
||||||
SHA="${{ github.sha }}" # This is the last commit to the branch.
|
|
||||||
REF=${GITHUB_REF#refs/heads/}
|
|
||||||
else
|
|
||||||
echo "ERROR: This action only supports pull requests and push events as triggers. Exiting with error."
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
echo "Commit SHA is $SHA"
|
|
||||||
echo "Branch is $REF"
|
|
||||||
echo "REF=$REF" >> $GITHUB_ENV
|
|
||||||
|
|
||||||
COMMIT_AUTHOR=$(gh api repos/${{ github.repository }}/commits/$SHA --jq .author.login) # .author.login might be null, but for dependabot it will always be there and cannot be spoofed in contrast to .commit.author.name
|
|
||||||
echo "The author of the last commit is $COMMIT_AUTHOR"
|
|
||||||
if [[ "$COMMIT_AUTHOR" == "dependabot[bot]" ]]; then
|
|
||||||
echo "The last commit was made by dependabot"
|
|
||||||
LAST_COMMIT_IS_BY_DEPENDABOT=true
|
|
||||||
else
|
|
||||||
echo "The last commit was made by $COMMIT_AUTHOR not by dependabot"
|
|
||||||
LAST_COMMIT_IS_BY_DEPENDABOT=false
|
|
||||||
fi
|
|
||||||
echo "LAST_COMMIT_IS_BY_DEPENDABOT=$LAST_COMMIT_IS_BY_DEPENDABOT" >> $GITHUB_ENV
|
|
||||||
env:
|
|
||||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
|
||||||
shell: bash
|
|
||||||
- name: Check if the last commit's message ends in "--regenerate-exemptions"
|
|
||||||
run: |
|
|
||||||
# Get commit message
|
|
||||||
COMMIT_MESSAGE=$(git log -1 --pretty=format:"%s")
|
|
||||||
if [[ "$COMMIT_MESSAGE" == *"--regenerate-exemptions" ]]; then
|
|
||||||
echo "The last commit message ends in --regenerate-exemptions"
|
|
||||||
REGEN_EXEMP=true
|
|
||||||
else
|
|
||||||
echo "The last commit message does not end in --regenerate-exemptions"
|
|
||||||
REGEN_EXEMP=false
|
|
||||||
fi
|
|
||||||
echo "REGEN_EXEMP=$REGEN_EXEMP" >> $GITHUB_ENV
|
|
||||||
shell: bash
|
|
||||||
- name: Check if the CI run happens in the context of a dependabot PR # Even if a PR is created by dependabot, the last commit can, and often should be, the regeneration of the cargo vet exemptions. It could also be from an individual making manual changes.
|
|
||||||
run: |
|
|
||||||
IN_DEPENDABOT_PR_CONTEXT="false"
|
|
||||||
if [[ $IS_PR == "true" && "${{ github.event.pull_request.user.login }}" == "dependabot[bot]" ]]; then
|
|
||||||
IN_DEPENDABOT_PR_CONTEXT="true"
|
|
||||||
echo "This CI run is in the context of PR by dependabot."
|
|
||||||
else
|
|
||||||
echo "This CI run is NOT in the context of PR by dependabot."
|
|
||||||
IN_DEPENDABOT_PR_CONTEXT="false"
|
|
||||||
fi
|
|
||||||
echo "IN_DEPENDABOT_PR_CONTEXT=$IN_DEPENDABOT_PR_CONTEXT" >> $GITHUB_ENV
|
|
||||||
shell: bash
|
|
||||||
- uses: actions/checkout@v5
|
|
||||||
if: env.IN_DEPENDABOT_PR_CONTEXT == 'true'
|
|
||||||
with:
|
|
||||||
token: ${{ secrets.CI_BOT_PAT }}
|
|
||||||
- name: In case of a dependabot PR, ensure that we are not in a detached HEAD state
|
|
||||||
if: env.IN_DEPENDABOT_PR_CONTEXT == 'true'
|
|
||||||
run: |
|
|
||||||
git fetch origin $REF # ensure that we are up to date.
|
|
||||||
git switch $REF # ensure that we are NOT in a detached HEAD state. This is important for the commit action in the end
|
|
||||||
shell: bash
|
|
||||||
- name: Regenerate cargo vet exemptions if we are in the context of a PR created by dependabot and the last commit is by dependabot or a regeneration of cargo vet exemptions was explicitly requested.
|
|
||||||
if: env.IN_DEPENDABOT_PR_CONTEXT == 'true' && (env.LAST_COMMIT_IS_BY_DEPENDABOT == 'true' || env.REGEN_EXEMP=='true') # Run only for Dependabot PRs or if specifically requested
|
|
||||||
run: cargo vet regenerate exemptions
|
|
||||||
- name: Commit and push changes if we are in the context of a PR created by dependabot and the last commit is by dependabot or a regeneration of cargo vet exemptions was explicitly requested.
|
|
||||||
if: env.IN_DEPENDABOT_PR_CONTEXT == 'true' && (env.LAST_COMMIT_IS_BY_DEPENDABOT == 'true' || env.REGEN_EXEMP=='true')
|
|
||||||
uses: stefanzweifel/git-auto-commit-action@v6
|
|
||||||
with:
|
|
||||||
commit_message: Regenerate cargo vet exemptions
|
|
||||||
commit_user_name: rosenpass-ci-bot[bot]
|
|
||||||
commit_user_email: noreply@rosenpass.eu
|
|
||||||
commit_author: Rosenpass CI Bot <noreply@rosenpass.eu>
|
|
||||||
env:
|
|
||||||
GITHUB_TOKEN: ${{ secrets.CI_BOT_PAT }}
|
|
||||||
- name: Invoke cargo-vet
|
|
||||||
run: cargo vet --locked
|
|
||||||
1
.gitignore
vendored
@@ -25,4 +25,3 @@ _markdown_*
|
|||||||
.vscode
|
.vscode
|
||||||
|
|
||||||
/output
|
/output
|
||||||
.nixos-test-history
|
|
||||||
|
|||||||
@@ -1,41 +1,38 @@
|
|||||||
# Contributing to Rosenpass
|
**Making a new Release of Rosenpass — Cooking Recipe**
|
||||||
|
|
||||||
## Common operations
|
If you have to change a file, do what it takes to get the change as commit on the main branch, then **start from step 0**.
|
||||||
|
If any other issue occurs
|
||||||
|
|
||||||
### Apply code formatting
|
0. Make sure you are in the root directory of the project
|
||||||
|
- `cd "$(git rev-parse --show-toplevel)"`
|
||||||
|
1. Make sure you locally checked out the head of the main branch
|
||||||
|
- `git stash --include-untracked && git checkout main && git pull`
|
||||||
|
2. Make sure all tests pass
|
||||||
|
- `cargo test --workspace --all-features`
|
||||||
|
3. Make sure the current version in `rosenpass/Cargo.toml` matches that in the [last release on GitHub](https://github.com/rosenpass/rosenpass/releases)
|
||||||
|
- Only normal releases count, release candidates and draft releases can be ignored
|
||||||
|
4. Pick the kind of release that you want to make (`major`, `minor`, `patch`, `rc`, ...)
|
||||||
|
- See `cargo release --help` for more information on the available release types
|
||||||
|
- Pick `rc` if in doubt
|
||||||
|
5. Try to release a new version
|
||||||
|
- `cargo release rc --package rosenpass`
|
||||||
|
- An issue was reported? Go fix it, start again with step 0!
|
||||||
|
6. Actually make the release
|
||||||
|
- `cargo release rc --package rosenpass --execute`
|
||||||
|
- Tentatively wait for any interactions, such as entering ssh keys etc.
|
||||||
|
- You may be asked for your ssh key multiple times!
|
||||||
|
|
||||||
Format rust code:
|
**Frequently Asked Questions (FAQ)**
|
||||||
|
|
||||||
```bash
|
- You have untracked files, which `cargo release` complains about?
|
||||||
cargo fmt
|
- `git stash --include-untracked`
|
||||||
```
|
- You cannot push to crates.io because you are not logged in?
|
||||||
|
- Follow the steps displayed in [`cargo login`](https://doc.rust-lang.org/cargo/commands/cargo-login.html)
|
||||||
Format rust code in markdown files:
|
- How is the release page added to [GitHub Releases](https://github.com/rosenpass/rosenpass/releases) itself?
|
||||||
|
- Our CI Pipeline will create the release, once `cargo release` pushed the new version tag to the repo. The new release should pop up almost immediately in [GitHub Releases](https://github.com/rosenpass/rosenpass/releases) after the [Actions/Release](https://github.com/rosenpass/rosenpass/actions/workflows/release.yaml) pipeline started.
|
||||||
```bash
|
- No new release pops up in the `Release` sidebar element on the [main page](https://github.com/rosenpass/rosenpass)
|
||||||
./format_rust_code.sh --mode fix
|
- Did you push a `rc` release? This view only shows non-draft release, but `rc` releases are considered as draft. See [Releases](https://github.com/rosenpass/rosenpass/releases) page to see all (including draft!) releases.
|
||||||
```
|
- The release page was created on GitHub, but there are no assets/artifacts other than the source code tar ball/zip?
|
||||||
|
- The artifacts are generated and pushed automatically to the release, but this takes some time (a couple of minutes). You can check the respective CI pipeline: [Actions/Release](https://github.com/rosenpass/rosenpass/actions/workflows/release.yaml), which should start immediately after `cargo release` pushed the new release tag to the repo. The release artifacts only are added later to the release, once all jobs in bespoke pipeline finished.
|
||||||
### Spawn a development environment with nix
|
- How are the release artifacts generated, and what are they?
|
||||||
|
- The release artifacts are built using one Nix derivation per platform, `nix build .#release-package`. It contains both statically linked versions of `rosenpass` itself and OCI container images.
|
||||||
```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
|
|
||||||
```
|
|
||||||
|
|||||||
1151
Cargo.lock
generated
73
Cargo.toml
@@ -2,17 +2,17 @@
|
|||||||
resolver = "2"
|
resolver = "2"
|
||||||
|
|
||||||
members = [
|
members = [
|
||||||
"rosenpass",
|
"rosenpass",
|
||||||
"cipher-traits",
|
"cipher-traits",
|
||||||
"ciphers",
|
"ciphers",
|
||||||
"util",
|
"util",
|
||||||
"constant-time",
|
"constant-time",
|
||||||
"oqs",
|
"oqs",
|
||||||
"to",
|
"to",
|
||||||
"fuzz",
|
"fuzz",
|
||||||
"secret-memory",
|
"secret-memory",
|
||||||
"rp",
|
"rp",
|
||||||
"wireguard-broker",
|
"wireguard-broker",
|
||||||
]
|
]
|
||||||
|
|
||||||
default-members = ["rosenpass", "rp", "wireguard-broker"]
|
default-members = ["rosenpass", "rp", "wireguard-broker"]
|
||||||
@@ -42,66 +42,51 @@ toml = "0.7.8"
|
|||||||
static_assertions = "1.1.0"
|
static_assertions = "1.1.0"
|
||||||
allocator-api2 = "0.2.14"
|
allocator-api2 = "0.2.14"
|
||||||
memsec = { git = "https://github.com/rosenpass/memsec.git", rev = "aceb9baee8aec6844125bd6612f92e9a281373df", features = [
|
memsec = { git = "https://github.com/rosenpass/memsec.git", rev = "aceb9baee8aec6844125bd6612f92e9a281373df", features = [
|
||||||
"alloc_ext",
|
"alloc_ext",
|
||||||
] }
|
] }
|
||||||
rand = "0.8.5"
|
rand = "0.8.5"
|
||||||
typenum = "1.17.0"
|
typenum = "1.17.0"
|
||||||
log = { version = "0.4.27" }
|
log = { version = "0.4.22" }
|
||||||
clap = { version = "4.5.23", features = ["derive"] }
|
clap = { version = "4.5.22", features = ["derive"] }
|
||||||
clap_mangen = "0.2.29"
|
clap_mangen = "0.2.24"
|
||||||
clap_complete = "4.5.40"
|
clap_complete = "4.5.38"
|
||||||
serde = { version = "1.0.217", features = ["derive"] }
|
serde = { version = "1.0.215", features = ["derive"] }
|
||||||
arbitrary = { version = "1.4.1", features = ["derive"] }
|
arbitrary = { version = "1.4.1", features = ["derive"] }
|
||||||
anyhow = { version = "1.0.98", features = ["backtrace", "std"] }
|
anyhow = { version = "1.0.94", features = ["backtrace", "std"] }
|
||||||
mio = { version = "1.0.3", features = ["net", "os-poll"] }
|
mio = { version = "1.0.3", features = ["net", "os-poll"] }
|
||||||
signal-hook-mio = { version = "0.2.4", features = ["support-v1_0"] }
|
|
||||||
signal-hook = "0.3.17"
|
|
||||||
oqs-sys = { version = "0.9.1", default-features = false, features = [
|
oqs-sys = { version = "0.9.1", default-features = false, features = [
|
||||||
'classic_mceliece',
|
'classic_mceliece',
|
||||||
'kyber',
|
'kyber',
|
||||||
] }
|
] }
|
||||||
blake2 = "0.10.6"
|
blake2 = "0.10.6"
|
||||||
sha3 = "0.10.8"
|
|
||||||
chacha20poly1305 = { version = "0.10.1", default-features = false, features = [
|
chacha20poly1305 = { version = "0.10.1", default-features = false, features = [
|
||||||
"std",
|
"std",
|
||||||
"heapless",
|
"heapless",
|
||||||
] }
|
] }
|
||||||
zerocopy = { version = "0.8.27", features = ["derive"] }
|
zerocopy = { version = "0.7.35", features = ["derive"] }
|
||||||
home = "=0.5.9" # 5.11 requires rustc 1.81
|
home = "0.5.9"
|
||||||
derive_builder = "0.20.1"
|
derive_builder = "0.20.1"
|
||||||
tokio = { version = "1.46", features = ["macros", "rt-multi-thread"] }
|
tokio = { version = "1.42", features = ["macros", "rt-multi-thread"] }
|
||||||
postcard = { version = "1.1.1", features = ["alloc"] }
|
postcard = { version = "1.1.1", features = ["alloc"] }
|
||||||
libcrux = { version = "0.0.2-pre.2" }
|
libcrux = { version = "0.0.2-pre.2" }
|
||||||
libcrux-chacha20poly1305 = { version = "0.0.2-beta.3" }
|
|
||||||
libcrux-ml-kem = { version = "0.0.2-beta.3" }
|
|
||||||
libcrux-blake2 = { git = "https://github.com/cryspen/libcrux.git", rev = "10ce653e9476" }
|
|
||||||
libcrux-test-utils = { git = "https://github.com/cryspen/libcrux.git", rev = "0ab6d2dd9c1f" }
|
|
||||||
hex-literal = { version = "0.4.1" }
|
hex-literal = { version = "0.4.1" }
|
||||||
hex = { version = "0.4.3" }
|
hex = { version = "0.4.3" }
|
||||||
heck = { version = "0.5.0" }
|
heck = { version = "0.5.0" }
|
||||||
libc = { version = "0.2" }
|
libc = { version = "0.2" }
|
||||||
errno = { version = "0.3.13" }
|
|
||||||
uds = { git = "https://github.com/rosenpass/uds" }
|
uds = { git = "https://github.com/rosenpass/uds" }
|
||||||
lazy_static = "1.5"
|
|
||||||
|
|
||||||
#Dev dependencies
|
#Dev dependencies
|
||||||
assert_tv = { version = "0.6.4" }
|
|
||||||
base64 = { version = "0.22.1" }
|
|
||||||
serial_test = "3.2.0"
|
serial_test = "3.2.0"
|
||||||
tempfile = "3"
|
tempfile = "3"
|
||||||
stacker = "0.1.21"
|
stacker = "0.1.17"
|
||||||
libfuzzer-sys = "0.4"
|
libfuzzer-sys = "0.4"
|
||||||
test_bin = "0.4.0"
|
test_bin = "0.4.0"
|
||||||
criterion = "0.5.1"
|
criterion = "0.4.0"
|
||||||
allocator-api2-tests = "0.2.15"
|
allocator-api2-tests = "0.2.15"
|
||||||
procspawn = { version = "1.0.1", features = ["test-support"] }
|
procspawn = { version = "1.0.1", features = ["test-support"] }
|
||||||
serde_json = { version = "1.0.140" }
|
|
||||||
bitflags = "2.9.3"
|
|
||||||
|
|
||||||
#Broker dependencies (might need cleanup or changes)
|
#Broker dependencies (might need cleanup or changes)
|
||||||
wireguard-uapi = { version = "3.0.0", features = ["xplatform"] }
|
wireguard-uapi = { version = "3.0.0", features = ["xplatform"] }
|
||||||
command-fds = "0.2.3"
|
command-fds = "0.2.3"
|
||||||
rustix = { version = "0.38.42", features = ["net", "fs", "process"] }
|
rustix = { version = "0.38.41", features = ["net", "fs"] }
|
||||||
futures = "0.3"
|
|
||||||
futures-util = "0.3"
|
|
||||||
x25519-dalek = "2"
|
|
||||||
|
|||||||
25
analysis/03_identity_hiding_initiator.entry.mpv
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
#define INITIATOR_TEST 1
|
||||||
|
|
||||||
|
#include "rosenpass/03_identity_hiding.mpv"
|
||||||
|
|
||||||
|
// nounif a:Atom, s:seed, a2:Atom;
|
||||||
|
// ConsumeSeed(a, s, a2) / 6300[conclusion].
|
||||||
|
|
||||||
|
nounif v:seed_prec; attacker(prepare_seed(trusted_seed( v )))/6217[hypothesis].
|
||||||
|
nounif v:seed; attacker(prepare_seed( v ))/6216[hypothesis].
|
||||||
|
nounif v:seed; attacker(rng_kem_sk( v ))/6215[hypothesis].
|
||||||
|
nounif v:seed; attacker(rng_key( v ))/6214[hypothesis].
|
||||||
|
nounif v:key_prec; attacker(prepare_key(trusted_key( v )))/6213[hypothesis].
|
||||||
|
nounif v:kem_sk_prec; attacker(prepare_kem_sk(trusted_kem_sk( v )))/6212[hypothesis].
|
||||||
|
nounif v:key; attacker(prepare_key( v ))/6211[hypothesis].
|
||||||
|
nounif v:kem_sk; attacker(prepare_kem_sk( v ))/6210[hypothesis].
|
||||||
|
nounif Spk:kem_sk_tmpl;
|
||||||
|
attacker(Creveal_kem_pk(Spk))/6110[conclusion].
|
||||||
|
nounif sid:SessionId, Ssskm:kem_sk_tmpl, Spsk:key_tmpl, Sspkt:kem_sk_tmpl, Seski:seed_tmpl, Ssptr:seed_tmpl;
|
||||||
|
attacker(Cinitiator( *sid, *Ssskm, *Spsk, *Sspkt, *Seski, *Ssptr ))/6109[conclusion].
|
||||||
|
nounif sid:SessionId, biscuit_no:Atom, Ssskm:kem_sk_tmpl, Spsk:key_tmpl, Sspkt:kem_sk_tmpl, Septi:seed_tmpl, Sspti:seed_tmpl, ih:InitHello_t;
|
||||||
|
attacker(Cinit_hello( *sid, *biscuit_no, *Ssskm, *Spsk, *Sspkt, *Septi, *Sspti, *ih ))/6108[conclusion].
|
||||||
|
nounif rh:RespHello_t;
|
||||||
|
attacker(Cresp_hello( *rh ))/6107[conclusion].
|
||||||
|
nounif Ssskm:kem_sk_tmpl, Spsk:key_tmpl, Sspkt:kem_sk_tmpl, ic:InitConf_t;
|
||||||
|
attacker(Cinit_conf( *Ssskm, *Spsk, *Sspkt, *ic ))/6106[conclusion].
|
||||||
96
analysis/03_identity_hiding_responder.entry.mpv
Normal file
@@ -0,0 +1,96 @@
|
|||||||
|
#define RESPONDER_TEST 1
|
||||||
|
|
||||||
|
#include "rosenpass/03_identity_hiding.mpv"
|
||||||
|
|
||||||
|
// select k:kem_pk,ih: InitHello_t; attacker(prf(prf(prf(prf(key0, PROTOCOL), MAC), kem_pk2b(k) ), IH2b(ih))) phase 1/6300[hypothesis].
|
||||||
|
|
||||||
|
// select epki:kem_pk, sctr:bits, pidiC:bits, auth:bits, epki2:kem_pk, sctr2:bits, pidiC2:bits, auth2:bits;
|
||||||
|
// mess(D, prf(prf(prf(prf(key0,PROTOCOL),MAC),kem_pk2b(kem_pub(trusted_kem_sk(responder1)))),
|
||||||
|
// IH2b(InitHello(secure_sidi, *epki, *sctr, *pidiC, *auth)))
|
||||||
|
// ) [hypothesis, conclusion].
|
||||||
|
|
||||||
|
// select epki:kem_pk, sctr:bits, pidiC:bits, auth:bits, epki2:kem_pk, sctr2:bits, pidiC2:bits, auth2:bits;
|
||||||
|
// attacker(choice[prf(prf(prf(prf(key0,PROTOCOL),MAC),kem_pk2b(kem_pub(trusted_kem_sk(responder1)))),
|
||||||
|
// IH2b(InitHello(secure_sidi, *epki, *sctr, *pidiC, *auth))),
|
||||||
|
|
||||||
|
// prf(prf(prf(prf(key0,PROTOCOL),MAC),kem_pk2b(kem_pub(trusted_kem_sk(responder2)))),
|
||||||
|
// IH2b(InitHello(secure_sidi, *epki2, *sctr2, *pidiC2, *auth2)))]
|
||||||
|
// ) [hypothesis, conclusion].
|
||||||
|
|
||||||
|
// select
|
||||||
|
// attacker(prf(prf(key0,PROTOCOL),MAC)) [hypothesis, conclusion].
|
||||||
|
|
||||||
|
// select
|
||||||
|
// attacker(prf(key0,PROTOCOL)) [conclusion].
|
||||||
|
|
||||||
|
// select
|
||||||
|
// attacker(key0) [conclusion].
|
||||||
|
|
||||||
|
// select
|
||||||
|
// attacker(PROTOCOL) [conclusion].
|
||||||
|
|
||||||
|
// select
|
||||||
|
// attacker(kem_pub(trusted_kem_sk(responder1))) /9999 [hypothesis, conclusion].
|
||||||
|
|
||||||
|
// select
|
||||||
|
// attacker(kem_pub(trusted_kem_sk(responder2))) /9999 [hypothesis, conclusion].
|
||||||
|
|
||||||
|
// nounif ih:InitHello_t;
|
||||||
|
// attacker(ih) / 9999 [hypothesis].
|
||||||
|
|
||||||
|
// nounif rh:RespHello_t;
|
||||||
|
// attacker(rh) / 9999 [hypothesis].
|
||||||
|
|
||||||
|
// nounif ic:InitConf_t;
|
||||||
|
// attacker(ic) / 9999 [hypothesis].
|
||||||
|
|
||||||
|
// nounif k:key;
|
||||||
|
// attacker(ck_hs_enc( *k )) [hypothesis, conclusion].
|
||||||
|
|
||||||
|
// nounif k:key;
|
||||||
|
// attacker(ck_hs_enc( *k )) phase 1 [hypothesis, conclusion].
|
||||||
|
|
||||||
|
// nounif k:key, b:bits;
|
||||||
|
// attacker(ck_mix( *k , *b )) [hypothesis, conclusion].
|
||||||
|
|
||||||
|
// nounif k:key, b:bits;
|
||||||
|
// attacker(ck_mix( *k , *b ))phase 1 [hypothesis, conclusion].
|
||||||
|
|
||||||
|
// // select k:kem_pk, epki2:kem_pk, sctr2:bits, pidiC2:bits, auth2:bits, epki:kem_pk, sctr:bits, pidiC:bits, auth:bits;
|
||||||
|
// // attacker(choice[Envelope(prf(prf(prf(prf(key0,PROTOCOL),MAC),kem_pub(trusted_kem_sk(responder1))),
|
||||||
|
// // InitHello(secure_sidi, *epki2, *sctr2, *pidiC2, *auth2)
|
||||||
|
// // ), InitHello(secure_sidi, *epki2, *sctr2, *pidiC2, *auth2))
|
||||||
|
// // Envelope(prf(prf(prf(prf(key0,PROTOCOL),MAC),kem_pub(trusted_kem_sk(responder2))),
|
||||||
|
// // InitHello(secure_sidi, *epki, *sctr, *pidiC, *auth)),
|
||||||
|
// // InitHello(secure_sidi, *epki, *sctr, *pidiC, *auth))
|
||||||
|
// // ]) / 9999[hypothesis, conclusion].
|
||||||
|
|
||||||
|
// nounif k:key, b1:bits, b2:bits;
|
||||||
|
// attacker(xaead_enc( *k, *b1, *b2)) / 9999[hypothesis,conclusion].
|
||||||
|
|
||||||
|
// nounif pk:kem_pk, k:key;
|
||||||
|
// attacker(kem_enc( *pk , *k )) / 9999[hypothesis,conclusion].
|
||||||
|
|
||||||
|
// nounif sid:SessionId, biscuit_no:Atom, Ssskm:kem_sk_tmpl, Spsk:key_tmpl, Sspkt:kem_sk_tmpl, Septi:seed_tmpl, Sspti:seed_tmpl, ih:InitHello_t;
|
||||||
|
// attacker(Cinit_hello( *sid, *biscuit_no, *Ssskm, *Spsk, *Sspkt, *Septi, *Sspti, *ih ))/9999[hypothesis, conclusion].
|
||||||
|
// nounif Ssskm:kem_sk_tmpl, Spsk:key_tmpl, Sspkt:kem_sk_tmpl, ic:InitConf_t;
|
||||||
|
// attacker(Cinit_conf( *Ssskm, *Spsk, *Sspkt, *ic ))/9999[hypothesis, conclusion].
|
||||||
|
// nounif sid:SessionId, Ssskm:kem_sk_tmpl, Spsk:key_tmpl, Sspkt:kem_sk_tmpl, Seski:seed_tmpl, Ssptr:seed_tmpl;
|
||||||
|
// attacker(Cinitiator( *sid, *Ssskm, *Spsk, *Sspkt, *Seski, *Ssptr )) /9999 [hypothesis, conclusion].
|
||||||
|
|
||||||
|
// nounif sid:SessionId, biscuit_no:Atom, Ssskm:kem_sk_tmpl, Spsk:key_tmpl, Sspkt:kem_sk_tmpl, Septi:seed_tmpl, Sspti:seed_tmpl, ih:InitHello_t;
|
||||||
|
// mess(C, Cinit_hello( *sid, *biscuit_no, *Ssskm, *Spsk, *Sspkt, *Septi, *Sspti, *ih ))/9999[hypothesis, conclusion].
|
||||||
|
// nounif Ssskm:kem_sk_tmpl, Spsk:key_tmpl, Sspkt:kem_sk_tmpl, ic:InitConf_t;
|
||||||
|
// mess(C, Cinit_conf( *Ssskm, *Spsk, *Sspkt, *ic ))/9999[hypothesis, conclusion].
|
||||||
|
// nounif sid:SessionId, Ssskm:kem_sk_tmpl, Spsk:key_tmpl, Sspkt:kem_sk_tmpl, Seski:seed_tmpl, Ssptr:seed_tmpl;
|
||||||
|
// mess(C, Cinitiator( *sid, *Ssskm, *Spsk, *Sspkt, *Seski, *Ssptr )) /9999 [hypothesis, conclusion].
|
||||||
|
// nounif rh:RespHello_t;
|
||||||
|
// attacker(Cresp_hello( *rh ))[conclusion].
|
||||||
|
// nounif v:seed_prec; attacker(prepare_seed(trusted_seed( v )))/6217[hypothesis].
|
||||||
|
// nounif v:seed; attacker(prepare_seed( v ))/6216[hypothesis].
|
||||||
|
// nounif v:seed; attacker(rng_kem_sk( v ))/6215[hypothesis].
|
||||||
|
// nounif v:seed; attacker(rng_key( v ))/6214[hypothesis].
|
||||||
|
// nounif v:key_prec; attacker(prepare_key(trusted_key( v )))/6213[hypothesis].
|
||||||
|
// nounif v:kem_sk_prec; attacker(prepare_kem_sk(trusted_kem_sk( v )))/6212[hypothesis].
|
||||||
|
// nounif v:key; attacker(prepare_key( v ))/6211[hypothesis].
|
||||||
|
// nounif v:kem_sk; attacker(prepare_kem_sk( v ))/6210[hypothesis].
|
||||||
29
analysis/03_identity_hiding_test.entry.mpv
Normal file
@@ -0,0 +1,29 @@
|
|||||||
|
#define INITIATOR_TEST 1
|
||||||
|
#define CUSTOM_MAIN 1
|
||||||
|
|
||||||
|
#include "rosenpass/03_identity_hiding.mpv"
|
||||||
|
|
||||||
|
let Oinitiator_bad_actor_inner(sk_tmp:kem_sk_prec) =
|
||||||
|
|
||||||
|
in(C, Cinitiator(sidi, Ssskm, Spsk, Sspkt, Seski, Ssptr));
|
||||||
|
|
||||||
|
#if RANDOMIZED_CALL_IDS
|
||||||
|
new call:Atom;
|
||||||
|
#else
|
||||||
|
call <- Cinitiator(sidi, Ssskm, Spsk, Sspkt, Seski, Ssptr);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
in(C, last_cookie:key);
|
||||||
|
tmpl <- make_trusted_kem_sk(sk_tmp);
|
||||||
|
out(C, setup_kem_sk(tmpl));
|
||||||
|
Oinitiator_inner(sidi, Ssskm, Spsk, tmpl, Seski, Ssptr, last_cookie, C, call).
|
||||||
|
|
||||||
|
let Oinitiator_bad_actor() =
|
||||||
|
Oinitiator_bad_actor_inner(responder1) | Oinitiator_bad_actor_inner(responder2) | Oinitiator_bad_actor_inner(initiator1) | Oinitiator_bad_actor_inner(initiator2).
|
||||||
|
|
||||||
|
|
||||||
|
let identity_hiding_main2() =
|
||||||
|
0 | Oinitiator_bad_actor() | rosenpass_main2() | participants_communication() | phase 1; secretCommunication().
|
||||||
|
|
||||||
|
|
||||||
|
let main = identity_hiding_main2.
|
||||||
136
analysis/04_dos_protection.entry.mpv
Normal file
@@ -0,0 +1,136 @@
|
|||||||
|
#define CHAINING_KEY_EVENTS 1
|
||||||
|
#define MESSAGE_TRANSMISSION_EVENTS 0
|
||||||
|
#define SESSION_START_EVENTS 0
|
||||||
|
#define RANDOMIZED_CALL_IDS 0
|
||||||
|
#define COOKIE_EVENTS 1
|
||||||
|
#define KEM_EVENTS 1
|
||||||
|
|
||||||
|
#include "config.mpv"
|
||||||
|
#include "prelude/basic.mpv"
|
||||||
|
#include "crypto/key.mpv"
|
||||||
|
#include "crypto/kem.mpv"
|
||||||
|
#include "rosenpass/handshake_state.mpv"
|
||||||
|
|
||||||
|
/* The cookie data structure is implemented based on the WireGuard protocol.
|
||||||
|
* The ip and port is based purely on the public key and the implementation of the private cookie key is intended to mirror the biscuit key.
|
||||||
|
* The code tests the response to a possible DOS attack by setting up alternative branches for the protocol
|
||||||
|
* processes: Oinit_conf, Oinit_hello and resp_hello to simulate what happens when the responder or initiator is overloaded.
|
||||||
|
* When under heavy load a valid cookie is required. When such a cookie is not present a cookie message is sent as a response.
|
||||||
|
* Queries then test to make sure that expensive KEM operations are only conducted after a cookie has been successfully validated.
|
||||||
|
*/
|
||||||
|
|
||||||
|
type CookieMsg_t.
|
||||||
|
fun CookieMsg(
|
||||||
|
SessionId, // sender
|
||||||
|
bits, // nonce
|
||||||
|
bits // cookie
|
||||||
|
) : CookieMsg_t [data].
|
||||||
|
|
||||||
|
#define COOKIE_EVENTS(eventLbl) \
|
||||||
|
COOKIE_EV(event MCAT(eventLbl, _UnderLoadEV) (SessionId, SessionId, Atom).) \
|
||||||
|
COOKIE_EV(event MCAT(eventLbl, _CookieValidated) (SessionId, SessionId, Atom).) \
|
||||||
|
COOKIE_EV(event MCAT(eventLbl, _CookieSent) (SessionId, SessionId, Atom, CookieMsg_t).)
|
||||||
|
|
||||||
|
fun cookie_key(kem_sk) : key [private].
|
||||||
|
fun ip_and_port(kem_pk):bits.
|
||||||
|
letfun create_mac2_key(sskm:kem_sk, spkt:kem_pk) = prf(cookie_key(sskm), ip_and_port(spkt)).
|
||||||
|
letfun create_cookie(sskm:kem_sk, spkm:kem_pk, spkt:kem_pk, nonce:bits, msg:bits) = xaead_enc(lprf2(COOKIE, kem_pk2b(spkm), nonce),
|
||||||
|
k2b(create_mac2_key(sskm, spkm)), msg).
|
||||||
|
|
||||||
|
#define COOKIE_PROCESS(eventLbl, innerFunc) \
|
||||||
|
new nonce:bits; \
|
||||||
|
in(C, Ccookie(mac1, mac2)); \
|
||||||
|
COOKIE_EV(event MCAT(eventLbl, _UnderLoadEV) (sidi, sidr, call);) \
|
||||||
|
msgB <- Envelope(mac1, msg); \
|
||||||
|
mac2_key <- create_mac2_key(sskm, spkt); \
|
||||||
|
if k2b(create_mac2(mac2_key, msgB)) = mac2 then \
|
||||||
|
COOKIE_EV(event MCAT(eventLbl, _CookieValidated) (sidi, sidr, call);) \
|
||||||
|
innerFunc \
|
||||||
|
else \
|
||||||
|
cookie <- create_cookie(sskm, spkm, spkt, nonce, msg); \
|
||||||
|
cookie_msg <- CookieMsg(sidi, nonce, cookie); \
|
||||||
|
COOKIE_EV(event MCAT(eventLbl, _CookieSent) (sidi, sidr, call, cookie_msg);) \
|
||||||
|
out(C, cookie_msg). \
|
||||||
|
|
||||||
|
#include "rosenpass/oracles.mpv"
|
||||||
|
|
||||||
|
#include "rosenpass/responder.macro"
|
||||||
|
COOKIE_EVENTS(Oinit_conf)
|
||||||
|
let Oinit_conf_underLoad() =
|
||||||
|
in(C, Cinit_conf(Ssskm, Spsk, Sspkt, ic));
|
||||||
|
in(C, last_cookie:bits);
|
||||||
|
|
||||||
|
msg <- IC2b(ic);
|
||||||
|
let InitConf(sidi, sidr, biscuit, auth) = ic in
|
||||||
|
|
||||||
|
new call:Atom;
|
||||||
|
|
||||||
|
SETUP_HANDSHAKE_STATE()
|
||||||
|
|
||||||
|
COOKIE_PROCESS(Oinit_conf, Oinit_conf_inner(Ssskm, Spsk, Sspkt, ic, call))
|
||||||
|
|
||||||
|
#include "rosenpass/responder.macro"
|
||||||
|
COOKIE_EVENTS(Oinit_hello)
|
||||||
|
let Oinit_hello_underLoad() =
|
||||||
|
|
||||||
|
in(C, Cinit_hello(sidr, biscuit_no, Ssskm, Spsk, Sspkt, Septi, Sspti, ih));
|
||||||
|
in(C, Oinit_hello_last_cookie:key);
|
||||||
|
new call:Atom;
|
||||||
|
|
||||||
|
msg <- IH2b(ih);
|
||||||
|
let InitHello(sidi, epki, sctr, pidic, auth) = ih in
|
||||||
|
SETUP_HANDSHAKE_STATE()
|
||||||
|
|
||||||
|
COOKIE_PROCESS(Oinit_hello, Oinit_hello_inner(sidr, biscuit_no, Ssskm, Spsk, Sspkt, Septi, Sspti, ih, Oinit_hello_last_cookie, C, call))
|
||||||
|
|
||||||
|
let rosenpass_dos_main() = 0
|
||||||
|
| !Oreveal_kem_pk
|
||||||
|
| REP(INITIATOR_BOUND, Oinitiator)
|
||||||
|
| REP(RESPONDER_BOUND, Oinit_hello)
|
||||||
|
| REP(RESPONDER_BOUND, Oinit_conf)
|
||||||
|
| REP(RESPONDER_BOUND, Oinit_hello_underLoad)
|
||||||
|
| REP(RESPONDER_BOUND, Oinit_conf_underLoad).
|
||||||
|
|
||||||
|
let main = rosenpass_dos_main.
|
||||||
|
|
||||||
|
select cookie:CookieMsg_t; attacker(cookie)/6220[hypothesis].
|
||||||
|
nounif v:key; attacker(prepare_key( v ))/6217[hypothesis].
|
||||||
|
nounif v:seed; attacker(prepare_seed( v ))/6216[hypothesis].
|
||||||
|
nounif v:seed; attacker(prepare_seed( v ))/6216[hypothesis].
|
||||||
|
nounif v:seed; attacker(rng_kem_sk( v ))/6215[hypothesis].
|
||||||
|
nounif v:seed; attacker(rng_key( v ))/6214[hypothesis].
|
||||||
|
nounif v:kem_sk; attacker(prepare_kem_sk( v ))/6210[hypothesis].
|
||||||
|
|
||||||
|
// nounif Spk:kem_sk_tmpl;
|
||||||
|
// attacker(Creveal_kem_pk(Spk))/6110[conclusion].
|
||||||
|
// nounif sid:SessionId, Ssskm:kem_sk_tmpl, Spsk:key_tmpl, Sspkt:kem_sk_tmpl, Seski:seed_tmpl, Ssptr:seed_tmpl;
|
||||||
|
// attacker(Cinitiator( *sid, *Ssskm, *Spsk, *Sspkt, *Seski, *Ssptr ))/6109[conclusion].
|
||||||
|
// nounif sid:SessionId, biscuit_no:Atom, Ssskm:kem_sk_tmpl, Spsk:key_tmpl, Sspkt:kem_sk_tmpl, Septi:seed_tmpl, Sspti:seed_tmpl, ih:InitHello_t;
|
||||||
|
// attacker(Cinit_hello( *sid, *biscuit_no, *Ssskm, *Spsk, *Sspkt, *Septi, *Sspti, *ih ))/6108[conclusion].
|
||||||
|
nounif rh:RespHello_t;
|
||||||
|
attacker(Cresp_hello( *rh ))/6107[conclusion].
|
||||||
|
nounif Ssskm:kem_sk_tmpl, Spsk:key_tmpl, Sspkt:kem_sk_tmpl, ic:InitConf_t;
|
||||||
|
attacker(Cinit_conf( *Ssskm, *Spsk, *Sspkt, *ic ))/6106[conclusion].
|
||||||
|
|
||||||
|
@reachable "DOS protection: cookie sent"
|
||||||
|
query sidi:SessionId, sidr:SessionId, call:Atom, cookieMsg:CookieMsg_t;
|
||||||
|
event (Oinit_hello_CookieSent(sidi, sidr, call, cookieMsg)).
|
||||||
|
|
||||||
|
@lemma "DOS protection: Oinit_hello kem use when under load implies validated cookie"
|
||||||
|
lemma sidi:SessionId, sidr:SessionId, call:Atom;
|
||||||
|
event(Oinit_hello_UnderLoadEV(sidi, sidr, call))
|
||||||
|
&& event(Oinit_hello_KemUse(sidi, sidr, call))
|
||||||
|
==> event(Oinit_hello_CookieValidated(sidi, sidr, call)).
|
||||||
|
|
||||||
|
@lemma "DOS protection: Oinit_conf kem use when under load implies validated cookie"
|
||||||
|
lemma sidi:SessionId, sidr:SessionId, call:Atom;
|
||||||
|
event(Oinit_conf_UnderLoadEV(sidi, sidr, call))
|
||||||
|
&& event(Oinit_conf_KemUse(sidi, sidr, call))
|
||||||
|
==> event(Oinit_conf_CookieValidated(sidi, sidr, call)).
|
||||||
|
|
||||||
|
@lemma "DOS protection: Oresp_hello kem use when under load implies validated cookie"
|
||||||
|
lemma sidi:SessionId, sidr:SessionId, call:Atom;
|
||||||
|
event(Oresp_hello_UnderLoadEV(sidi, sidr, call))
|
||||||
|
&& event(Oresp_hello_KemUse(sidi, sidr, call))
|
||||||
|
==> event(Oresp_hello_CookieValidated(sidi, sidr, call)).
|
||||||
|
|
||||||
@@ -58,7 +58,7 @@ let secure_init_hello(initiator: kem_sk_tmpl, sidi : SessionId, psk: key_tmpl, r
|
|||||||
|
|
||||||
new epkit:kem_pk; // epki
|
new epkit:kem_pk; // epki
|
||||||
new sctrt:bits; // sctr
|
new sctrt:bits; // sctr
|
||||||
new pidi_ct:bits; // pidi_ct
|
new pidiCt:bits; // pidiC
|
||||||
new autht:bits; // auth
|
new autht:bits; // auth
|
||||||
|
|
||||||
NEW_TRUSTED_SEED(seski_trusted_seed)
|
NEW_TRUSTED_SEED(seski_trusted_seed)
|
||||||
@@ -70,9 +70,9 @@ let secure_init_hello(initiator: kem_sk_tmpl, sidi : SessionId, psk: key_tmpl, r
|
|||||||
|
|
||||||
let secure_resp_hello(initiator: kem_sk_tmpl, responder: kem_sk_tmpl, sidi:SessionId, sidr:SessionId, biscuit_no:Atom, psk:key_tmpl) =
|
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, pidi_ct, auth));
|
in(D, InitHello(=secure_sidi, epki, sctr, pidiC, auth));
|
||||||
|
|
||||||
ih <- InitHello(sidi, epki, sctr, pidi_ct, auth);
|
ih <- InitHello(sidi, epki, sctr, pidiC, auth);
|
||||||
NEW_TRUSTED_SEED(septi_trusted_seed)
|
NEW_TRUSTED_SEED(septi_trusted_seed)
|
||||||
NEW_TRUSTED_SEED(sspti_trusted_seed)
|
NEW_TRUSTED_SEED(sspti_trusted_seed)
|
||||||
new last_cookie:key;
|
new last_cookie:key;
|
||||||
|
|||||||
@@ -19,7 +19,7 @@ fun CookieMsg(
|
|||||||
COOKIE_EV(event MCAT(eventLbl, _UnderLoadEV) (spkm, spkt, last_cookie);) \
|
COOKIE_EV(event MCAT(eventLbl, _UnderLoadEV) (spkm, spkt, last_cookie);) \
|
||||||
msgB <- Envelope(mac1, RH2b(rh)); \
|
msgB <- Envelope(mac1, RH2b(rh)); \
|
||||||
mac2_key <- create_mac2_key(sskm, spkt) \
|
mac2_key <- create_mac2_key(sskm, spkt) \
|
||||||
let RespHello(sidi, sidr, ecti, scti, biscuit_ct, auth) = rh in \
|
let RespHello(sidi, sidr, ecti, scti, biscuit, auth) = rh in \
|
||||||
if Envelope(mac2_key, msgB) = mac2 then \
|
if Envelope(mac2_key, msgB) = mac2 then \
|
||||||
COOKIE_EV(event MCAT(eventLbl, _CookieValidated) (spkm, last_cookie);) \
|
COOKIE_EV(event MCAT(eventLbl, _CookieValidated) (spkm, last_cookie);) \
|
||||||
innerFunc \
|
innerFunc \
|
||||||
|
|||||||
@@ -143,10 +143,10 @@ letfun ENCRYPT_AND_MIX(ct, pt) \
|
|||||||
// TODO: Migrate kems to use binary ciphertexts directly
|
// TODO: Migrate kems to use binary ciphertexts directly
|
||||||
#define ENCAPS_AND_MIX(ct, pk, shk) \
|
#define ENCAPS_AND_MIX(ct, pk, shk) \
|
||||||
ct <- kem_enc(pk, shk); \
|
ct <- kem_enc(pk, shk); \
|
||||||
MIX3(kem_pk2b(pk), k2b(shk), ct)
|
MIX3(kem_pk2b(pk), ct, k2b(shk))
|
||||||
#define DECAPS_AND_MIX(sk, pk, ct) \
|
#define DECAPS_AND_MIX(sk, pk, ct) \
|
||||||
DUMMY(shk) <- kem_dec(sk, ct); \
|
DUMMY(shk) <- kem_dec(sk, ct); \
|
||||||
MIX3(kem_pk2b(pk), k2b(DUMMY(shk)), ct)
|
MIX3(kem_pk2b(pk), ct, k2b(DUMMY(shk)))
|
||||||
|
|
||||||
|
|
||||||
// biscuits
|
// biscuits
|
||||||
|
|||||||
@@ -86,8 +86,8 @@ MTX_EV( event RHRjct(RespHello_t, key, kem_sk, kem_pk). )
|
|||||||
MTX_EV( event ICSent(RespHello_t, InitConf_t, key, kem_sk, kem_pk). )
|
MTX_EV( event ICSent(RespHello_t, InitConf_t, key, kem_sk, kem_pk). )
|
||||||
SES_EV( event InitiatorSession(RespHello_t, key). )
|
SES_EV( event InitiatorSession(RespHello_t, key). )
|
||||||
let Oresp_hello(HS_DECL_ARGS) =
|
let Oresp_hello(HS_DECL_ARGS) =
|
||||||
in(C, Cresp_hello(RespHello(sidr, =sidi, ecti, scti, biscuit_ct, auth)));
|
in(C, Cresp_hello(RespHello(sidr, =sidi, ecti, scti, biscuit, auth)));
|
||||||
rh <- RespHello(sidr, sidi, ecti, scti, biscuit_ct, auth);
|
rh <- RespHello(sidr, sidi, ecti, scti, biscuit, auth);
|
||||||
/* try */ let ic = (
|
/* try */ let ic = (
|
||||||
ck_ini <- ck;
|
ck_ini <- ck;
|
||||||
RESPHELLO_CONSUME()
|
RESPHELLO_CONSUME()
|
||||||
@@ -124,7 +124,7 @@ let Oinit_hello() =
|
|||||||
call <- Cinit_hello(sidr, biscuit_no, Ssskm, Spsk, Sspkt, Septi, Sspti, ih);
|
call <- Cinit_hello(sidr, biscuit_no, Ssskm, Spsk, Sspkt, Septi, Sspti, ih);
|
||||||
#endif
|
#endif
|
||||||
// TODO: This is ugly
|
// TODO: This is ugly
|
||||||
let InitHello(sidi, epki, sctr, pidi_ct, auth) = ih in
|
let InitHello(sidi, epki, sctr, pidiC, auth) = ih in
|
||||||
SETUP_HANDSHAKE_STATE()
|
SETUP_HANDSHAKE_STATE()
|
||||||
eski <- kem_sk0;
|
eski <- kem_sk0;
|
||||||
epti <- rng_key(setup_seed(Septi)); // RHR4
|
epti <- rng_key(setup_seed(Septi)); // RHR4
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ fun InitHello(
|
|||||||
SessionId, // sidi
|
SessionId, // sidi
|
||||||
kem_pk, // epki
|
kem_pk, // epki
|
||||||
bits, // sctr
|
bits, // sctr
|
||||||
bits, // pidi_ct
|
bits, // pidiC
|
||||||
bits // auth
|
bits // auth
|
||||||
) : InitHello_t [data].
|
) : InitHello_t [data].
|
||||||
|
|
||||||
@@ -17,16 +17,16 @@ fun InitHello(
|
|||||||
/* not handled here */ /* IHI3 */ \
|
/* not handled here */ /* IHI3 */ \
|
||||||
MIX2(sid2b(sidi), kem_pk2b(epki)) /* IHI4 */ \
|
MIX2(sid2b(sidi), kem_pk2b(epki)) /* IHI4 */ \
|
||||||
ENCAPS_AND_MIX(sctr, spkr, sptr) /* IHI5 */ \
|
ENCAPS_AND_MIX(sctr, spkr, sptr) /* IHI5 */ \
|
||||||
ENCRYPT_AND_MIX(pidi_ct, pidi) /* IHI6 */ \
|
ENCRYPT_AND_MIX(pidiC, pidi) /* IHI6 */ \
|
||||||
MIX2(kem_pk2b(spki), k2b(psk)) /* IHI7 */ \
|
MIX2(kem_pk2b(spki), k2b(psk)) /* IHI7 */ \
|
||||||
ENCRYPT_AND_MIX(auth, empty) /* IHI8 */ \
|
ENCRYPT_AND_MIX(auth, empty) /* IHI8 */ \
|
||||||
ih <- InitHello(sidi, epki, sctr, pidi_ct, auth);
|
ih <- InitHello(sidi, epki, sctr, pidiC, auth);
|
||||||
|
|
||||||
#define INITHELLO_CONSUME() \
|
#define INITHELLO_CONSUME() \
|
||||||
ck <- lprf1(CK_INIT, kem_pk2b(spkr)); /* IHR1 */ \
|
ck <- lprf1(CK_INIT, kem_pk2b(spkr)); /* IHR1 */ \
|
||||||
MIX2(sid2b(sidi), kem_pk2b(epki)) /* IHR4 */ \
|
MIX2(sid2b(sidi), kem_pk2b(epki)) /* IHR4 */ \
|
||||||
DECAPS_AND_MIX(sskr, spkr, sctr) /* IHR5 */ \
|
DECAPS_AND_MIX(sskr, spkr, sctr) /* IHR5 */ \
|
||||||
DECRYPT_AND_MIX(pid, pidi_ct) /* IHR6 */ \
|
DECRYPT_AND_MIX(pid, pidiC) /* IHR6 */ \
|
||||||
LOOKUP_SENDER(pid) /* IHR6 */ \
|
LOOKUP_SENDER(pid) /* IHR6 */ \
|
||||||
MIX2(kem_pk2b(spki), k2b(psk)) /* IHR7 */ \
|
MIX2(kem_pk2b(spki), k2b(psk)) /* IHR7 */ \
|
||||||
DECRYPT_AND_MIX(DUMMY(empty), auth)
|
DECRYPT_AND_MIX(DUMMY(empty), auth)
|
||||||
@@ -46,17 +46,17 @@ fun RespHello(
|
|||||||
MIX2(sid2b(sidr), sid2b(sidi)) /* RHR3 */ \
|
MIX2(sid2b(sidr), sid2b(sidi)) /* RHR3 */ \
|
||||||
ENCAPS_AND_MIX(ecti, epki, epti) /* RHR4 */ \
|
ENCAPS_AND_MIX(ecti, epki, epti) /* RHR4 */ \
|
||||||
ENCAPS_AND_MIX(scti, spki, spti) /* RHR5 */ \
|
ENCAPS_AND_MIX(scti, spki, spti) /* RHR5 */ \
|
||||||
STORE_BISCUIT(biscuit_ct) /* RHR6 */ \
|
STORE_BISCUIT(biscuit) /* RHR6 */ \
|
||||||
ENCRYPT_AND_MIX(auth, empty) /* RHR7 */ \
|
ENCRYPT_AND_MIX(auth, empty) /* RHR7 */ \
|
||||||
rh <- RespHello(sidr, sidi, ecti, scti, biscuit_ct, auth);
|
rh <- RespHello(sidr, sidi, ecti, scti, biscuit, auth);
|
||||||
|
|
||||||
#define RESPHELLO_CONSUME() \
|
#define RESPHELLO_CONSUME() \
|
||||||
let RespHello(sidr, sidi, ecti, scti, biscuit_ct, auth) = rh in \
|
let RespHello(sidr, sidi, ecti, scti, biscuit, auth) = rh in \
|
||||||
/* not handled here */ /* RHI2 */ \
|
/* not handled here */ /* RHI2 */ \
|
||||||
MIX2(sid2b(sidr), sid2b(sidi)) /* RHI3 */ \
|
MIX2(sid2b(sidr), sid2b(sidi)) /* RHI3 */ \
|
||||||
DECAPS_AND_MIX(eski, epki, ecti) /* RHI4 */ \
|
DECAPS_AND_MIX(eski, epki, ecti) /* RHI4 */ \
|
||||||
DECAPS_AND_MIX(sski, spki, scti) /* RHI5 */ \
|
DECAPS_AND_MIX(sski, spki, scti) /* RHI5 */ \
|
||||||
MIX(biscuit_ct) /* RHI6 */ \
|
MIX(biscuit) /* RHI6 */ \
|
||||||
DECRYPT_AND_MIX(DUMMY(empty), auth) /* RHI7 */
|
DECRYPT_AND_MIX(DUMMY(empty), auth) /* RHI7 */
|
||||||
|
|
||||||
type InitConf_t.
|
type InitConf_t.
|
||||||
@@ -70,11 +70,11 @@ fun InitConf(
|
|||||||
#define INITCONF_PRODUCE() \
|
#define INITCONF_PRODUCE() \
|
||||||
MIX2(sid2b(sidi), sid2b(sidr)) /* ICI3 */ \
|
MIX2(sid2b(sidi), sid2b(sidr)) /* ICI3 */ \
|
||||||
ENCRYPT_AND_MIX(auth, empty) /* ICI4 */ \
|
ENCRYPT_AND_MIX(auth, empty) /* ICI4 */ \
|
||||||
ic <- InitConf(sidi, sidr, biscuit_ct, auth);
|
ic <- InitConf(sidi, sidr, biscuit, auth);
|
||||||
|
|
||||||
#define INITCONF_CONSUME() \
|
#define INITCONF_CONSUME() \
|
||||||
let InitConf(sidi, sidr, biscuit_ct, auth) = ic in \
|
let InitConf(sidi, sidr, biscuit, auth) = ic in \
|
||||||
LOAD_BISCUIT(biscuit_no, biscuit_ct)/* ICR1 */ \
|
LOAD_BISCUIT(biscuit_no, biscuit) /* ICR1 */ \
|
||||||
ENCRYPT_AND_MIX(rh_auth, empty) /* ICIR */ \
|
ENCRYPT_AND_MIX(rh_auth, empty) /* ICIR */ \
|
||||||
ck_rh <- ck; /* ---- */ /* TODO: Move into oracles.mpv */ \
|
ck_rh <- ck; /* ---- */ /* TODO: Move into oracles.mpv */ \
|
||||||
MIX2(sid2b(sidi), sid2b(sidr)) /* ICR3 */ \
|
MIX2(sid2b(sidi), sid2b(sidr)) /* ICR3 */ \
|
||||||
|
|||||||
@@ -8,13 +8,5 @@ description = "Rosenpass internal traits for cryptographic primitives"
|
|||||||
homepage = "https://rosenpass.eu/"
|
homepage = "https://rosenpass.eu/"
|
||||||
repository = "https://github.com/rosenpass/rosenpass"
|
repository = "https://github.com/rosenpass/rosenpass"
|
||||||
readme = "readme.md"
|
readme = "readme.md"
|
||||||
rust-version = "1.77.0"
|
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
thiserror = { workspace = true }
|
|
||||||
rosenpass-to = { workspace = true }
|
|
||||||
|
|
||||||
[dev-dependencies]
|
|
||||||
rosenpass-oqs = { workspace = true }
|
|
||||||
rosenpass-secret-memory = { workspace = true }
|
|
||||||
anyhow = { workspace = true }
|
|
||||||
|
|||||||
@@ -2,4 +2,4 @@
|
|||||||
|
|
||||||
Rosenpass internal library providing traits for cryptographic primitives.
|
Rosenpass internal library providing traits for cryptographic primitives.
|
||||||
|
|
||||||
This is an internal library; no guarantee is made about its API at this point in time.
|
This is an internal library; not guarantee is made about its API at this point in time.
|
||||||
|
|||||||
@@ -1,137 +0,0 @@
|
|||||||
//! This module contains the traits for all the cryptographic algorithms used throughout Rosenpass.
|
|
||||||
//! These traits are marker traits that signal intent. They can also be used for trait objects.
|
|
||||||
|
|
||||||
/// Constants and trait for the Incorrect HMAC over Blake2b, with 256 key and hash length.
|
|
||||||
pub mod keyed_hash_incorrect_hmac_blake2b {
|
|
||||||
use crate::primitives::keyed_hash::*;
|
|
||||||
|
|
||||||
// These constants describe how they are used here, not what the algorithm defines.
|
|
||||||
|
|
||||||
/// The key length used in [`KeyedHashIncorrectHmacBlake2b`].
|
|
||||||
pub const KEY_LEN: usize = 32;
|
|
||||||
/// The hash length used in [`KeyedHashIncorrectHmacBlake2b`].
|
|
||||||
pub const HASH_LEN: usize = 32;
|
|
||||||
|
|
||||||
/// A [`KeyedHash`] that is an incorrect HMAC over Blake2 (a custom Rosenpass construction)
|
|
||||||
pub trait KeyedHashIncorrectHmacBlake2b: KeyedHash<KEY_LEN, HASH_LEN> {}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Constants and trait for Blake2b, with 256 key and hash length.
|
|
||||||
pub mod keyed_hash_blake2b {
|
|
||||||
use crate::primitives::keyed_hash::*;
|
|
||||||
|
|
||||||
// These constants describe how they are used here, not what the algorithm defines.
|
|
||||||
|
|
||||||
/// The key length used in [`KeyedHashBlake2b`].
|
|
||||||
pub const KEY_LEN: usize = 32;
|
|
||||||
/// The hash length used in [`KeyedHashBlake2b`].
|
|
||||||
pub const HASH_LEN: usize = 32;
|
|
||||||
|
|
||||||
/// A [`KeyedHash`] that is Blake2b
|
|
||||||
pub trait KeyedHashBlake2b: KeyedHash<KEY_LEN, HASH_LEN> {}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Constants and trait for SHAKE256, with 256 key and hash length.
|
|
||||||
pub mod keyed_hash_shake256 {
|
|
||||||
use crate::primitives::keyed_hash::*;
|
|
||||||
|
|
||||||
// These constants describe how they are used here, not what the algorithm defines.
|
|
||||||
|
|
||||||
/// The key length used in [`KeyedHashShake256`].
|
|
||||||
pub const KEY_LEN: usize = 32;
|
|
||||||
/// The hash length used in [`KeyedHashShake256`].
|
|
||||||
pub const HASH_LEN: usize = 32;
|
|
||||||
|
|
||||||
/// A [`KeyedHash`] that is SHAKE256.
|
|
||||||
pub trait KeyedHashShake256: KeyedHash<KEY_LEN, HASH_LEN> {}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Constants and trait for the ChaCha20Poly1305 AEAD
|
|
||||||
pub mod aead_chacha20poly1305 {
|
|
||||||
use crate::primitives::aead::*;
|
|
||||||
|
|
||||||
// See https://datatracker.ietf.org/doc/html/rfc7539#section-2.8
|
|
||||||
|
|
||||||
/// The key length used in [`AeadChaCha20Poly1305`].
|
|
||||||
pub const KEY_LEN: usize = 32;
|
|
||||||
/// The nonce length used in [`AeadChaCha20Poly1305`].
|
|
||||||
pub const NONCE_LEN: usize = 12;
|
|
||||||
/// The tag length used in [`AeadChaCha20Poly1305`].
|
|
||||||
pub const TAG_LEN: usize = 16;
|
|
||||||
|
|
||||||
/// An [`Aead`] that is ChaCha20Poly1305.
|
|
||||||
pub trait AeadChaCha20Poly1305: Aead<KEY_LEN, NONCE_LEN, TAG_LEN> {}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Constants and trait for the XChaCha20Poly1305 AEAD (i.e. ChaCha20Poly1305 with extended nonce
|
|
||||||
/// lengths)
|
|
||||||
pub mod aead_xchacha20poly1305 {
|
|
||||||
use crate::primitives::aead::*;
|
|
||||||
|
|
||||||
// See https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-xchacha-03
|
|
||||||
|
|
||||||
/// The key length used in [`AeadXChaCha20Poly1305`].
|
|
||||||
pub const KEY_LEN: usize = 32;
|
|
||||||
/// The nonce length used in [`AeadXChaCha20Poly1305`].
|
|
||||||
pub const NONCE_LEN: usize = 24;
|
|
||||||
/// The tag length used in [`AeadXChaCha20Poly1305`].
|
|
||||||
pub const TAG_LEN: usize = 16;
|
|
||||||
|
|
||||||
/// An [`Aead`] that is XChaCha20Poly1305.
|
|
||||||
pub trait AeadXChaCha20Poly1305: Aead<KEY_LEN, NONCE_LEN, TAG_LEN> {}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Constants and trait for the Kyber512 KEM
|
|
||||||
pub mod kem_kyber512 {
|
|
||||||
use crate::primitives::kem::*;
|
|
||||||
|
|
||||||
// page 39 of https://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.203.pdf
|
|
||||||
// (which is ml-kem instead of kyber, but it's the same)
|
|
||||||
|
|
||||||
/// The secret key length used in [`KemKyber512`].
|
|
||||||
pub const SK_LEN: usize = 1632;
|
|
||||||
|
|
||||||
/// The public key length used in [`KemKyber512`].
|
|
||||||
pub const PK_LEN: usize = 800;
|
|
||||||
|
|
||||||
/// The ciphertext length used in [`KemKyber512`].
|
|
||||||
pub const CT_LEN: usize = 768;
|
|
||||||
|
|
||||||
/// The shared key length used in [`KemKyber512`].
|
|
||||||
pub const SHK_LEN: usize = 32;
|
|
||||||
|
|
||||||
/// A [`Kem`] that is Kyber512.
|
|
||||||
pub trait KemKyber512: Kem<SK_LEN, PK_LEN, CT_LEN, SHK_LEN> {}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Constants and trait for the Classic McEliece 460896 KEM
|
|
||||||
pub mod kem_classic_mceliece460896 {
|
|
||||||
use crate::primitives::kem::*;
|
|
||||||
|
|
||||||
// page 6 of https://classic.mceliece.org/mceliece-impl-20221023.pdf
|
|
||||||
|
|
||||||
/// The secret key length used in [`KemClassicMceliece460896`].
|
|
||||||
pub const SK_LEN: usize = 13608;
|
|
||||||
|
|
||||||
/// The public key length used in [`KemClassicMceliece460896`].
|
|
||||||
pub const PK_LEN: usize = 524160;
|
|
||||||
|
|
||||||
/// The ciphertext length used in [`KemClassicMceliece460896`].
|
|
||||||
pub const CT_LEN: usize = 156;
|
|
||||||
|
|
||||||
/// The shared key length used in [`KemClassicMceliece460896`].
|
|
||||||
pub const SHK_LEN: usize = 32;
|
|
||||||
|
|
||||||
/// A [`Kem`] that is ClassicMceliece460896.
|
|
||||||
pub trait KemClassicMceliece460896: Kem<SK_LEN, PK_LEN, CT_LEN, SHK_LEN> {}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub use aead_chacha20poly1305::AeadChaCha20Poly1305;
|
|
||||||
pub use aead_xchacha20poly1305::AeadXChaCha20Poly1305;
|
|
||||||
|
|
||||||
pub use kem_classic_mceliece460896::KemClassicMceliece460896;
|
|
||||||
pub use kem_kyber512::KemKyber512;
|
|
||||||
|
|
||||||
pub use keyed_hash_blake2b::KeyedHashBlake2b;
|
|
||||||
pub use keyed_hash_incorrect_hmac_blake2b::KeyedHashIncorrectHmacBlake2b;
|
|
||||||
pub use keyed_hash_shake256::KeyedHashShake256;
|
|
||||||
@@ -5,128 +5,10 @@
|
|||||||
//!
|
//!
|
||||||
//! Conceptually KEMs are akin to public-key encryption, but instead of encrypting
|
//! 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
|
//! arbitrary data, KEMs are limited to the transmission of keys, randomly chosen during
|
||||||
|
//!
|
||||||
//! encapsulation.
|
//! encapsulation.
|
||||||
//!
|
//! The [KEM] Trait describes the basic API offered by a Key Encapsulation
|
||||||
//! The [Kem] Trait describes the basic API offered by a Key Encapsulation
|
//! Mechanism. Two implementations for it are provided, [StaticKEM] and [EphemeralKEM].
|
||||||
//! Mechanism. Two implementations for it are provided:
|
|
||||||
//! [Kyber512](../../rosenpass_oqs/kyber_512/enum.Kyber512.html) and
|
|
||||||
//! [ClassicMceliece460896](../../rosenpass_oqs/classic_mceliece_460896/enum.ClassicMceliece460896.html).
|
|
||||||
//!
|
|
||||||
//! An example where Alice generates a keypair and gives her public key to Bob, for Bob to
|
|
||||||
//! encapsulate a symmetric key and Alice to decapsulate it would look as follows.
|
|
||||||
//! In the example, we are using Kyber512, but any KEM that correctly implements the [Kem]
|
|
||||||
//! trait could be used as well.
|
|
||||||
//!```rust
|
|
||||||
//! use rosenpass_cipher_traits::Kem;
|
|
||||||
//! use rosenpass_oqs::Kyber512;
|
|
||||||
//! # use rosenpass_secret_memory::{secret_policy_use_only_malloc_secrets, Secret};
|
|
||||||
//!
|
|
||||||
//! type MyKem = Kyber512;
|
|
||||||
//! secret_policy_use_only_malloc_secrets();
|
|
||||||
//! let mut alice_sk: Secret<{ MyKem::SK_LEN }> = Secret::zero();
|
|
||||||
//! let mut alice_pk: [u8; MyKem::PK_LEN] = [0; MyKem::PK_LEN];
|
|
||||||
//! MyKem::keygen(alice_sk.secret_mut(), &mut alice_pk)?;
|
|
||||||
//!
|
|
||||||
//! let mut bob_shk: Secret<{ MyKem::SHK_LEN }> = Secret::zero();
|
|
||||||
//! let mut bob_ct: [u8; MyKem::CT_LEN] = [0; MyKem::CT_LEN];
|
|
||||||
//! MyKem::encaps(bob_shk.secret_mut(), &mut bob_ct, &mut alice_pk)?;
|
|
||||||
//!
|
|
||||||
//! let mut alice_shk: Secret<{ MyKem::SHK_LEN }> = Secret::zero();
|
|
||||||
//! MyKem::decaps(alice_shk.secret_mut(), alice_sk.secret_mut(), &mut bob_ct)?;
|
|
||||||
//!
|
|
||||||
//! # assert_eq!(alice_shk.secret(), bob_shk.secret());
|
|
||||||
//! # Ok::<(), anyhow::Error>(())
|
|
||||||
//!```
|
|
||||||
//!
|
|
||||||
//! Implementing the [Kem]-trait for a KEM is easy. Mostly, you must format the KEM's
|
|
||||||
//! keys, and ciphertext as `u8` slices. Below, we provide an example for how the trait can
|
|
||||||
//! be implemented using a **HORRIBLY INSECURE** DummyKem that only uses static values for keys
|
|
||||||
//! and ciphertexts as an example.
|
|
||||||
//!```rust
|
|
||||||
//!# use rosenpass_cipher_traits::Kem;
|
|
||||||
//!
|
|
||||||
//! struct DummyKem {}
|
|
||||||
//! impl Kem for DummyKem {
|
|
||||||
//!
|
|
||||||
//! // For this DummyKem, using String for errors is sufficient.
|
|
||||||
//! type Error = String;
|
|
||||||
//!
|
|
||||||
//! // For this DummyKem, we will use a single `u8` for everything
|
|
||||||
//! const SK_LEN: usize = 1;
|
|
||||||
//! const PK_LEN: usize = 1;
|
|
||||||
//! const CT_LEN: usize = 1;
|
|
||||||
//! const SHK_LEN: usize = 1;
|
|
||||||
//!
|
|
||||||
//! fn keygen(sk: &mut [u8], pk: &mut [u8]) -> Result<(), Self::Error> {
|
|
||||||
//! if sk.len() != Self::SK_LEN {
|
|
||||||
//! return Err("sk does not have the correct length!".to_string());
|
|
||||||
//! }
|
|
||||||
//! if pk.len() != Self::PK_LEN {
|
|
||||||
//! return Err("pk does not have the correct length!".to_string());
|
|
||||||
//! }
|
|
||||||
//! sk[0] = 42;
|
|
||||||
//! pk[0] = 21;
|
|
||||||
//! Ok(())
|
|
||||||
//! }
|
|
||||||
//!
|
|
||||||
//! fn encaps(shk: &mut [u8], ct: &mut [u8], pk: &[u8]) -> Result<(), Self::Error> {
|
|
||||||
//! if pk.len() != Self::PK_LEN {
|
|
||||||
//! return Err("pk does not have the correct length!".to_string());
|
|
||||||
//! }
|
|
||||||
//! if ct.len() != Self::CT_LEN {
|
|
||||||
//! return Err("ct does not have the correct length!".to_string());
|
|
||||||
//! }
|
|
||||||
//! if shk.len() != Self::SHK_LEN {
|
|
||||||
//! return Err("shk does not have the correct length!".to_string());
|
|
||||||
//! }
|
|
||||||
//! if pk[0] != 21 {
|
|
||||||
//! return Err("Invalid public key!".to_string());
|
|
||||||
//! }
|
|
||||||
//! ct[0] = 7;
|
|
||||||
//! shk[0] = 17;
|
|
||||||
//! Ok(())
|
|
||||||
//! }
|
|
||||||
//!
|
|
||||||
//! fn decaps(shk: &mut [u8], sk: &[u8], ct: &[u8]) -> Result<(), Self::Error> {
|
|
||||||
//! if sk.len() != Self::SK_LEN {
|
|
||||||
//! return Err("sk does not have the correct length!".to_string());
|
|
||||||
//! }
|
|
||||||
//! if ct.len() != Self::CT_LEN {
|
|
||||||
//! return Err("ct does not have the correct length!".to_string());
|
|
||||||
//! }
|
|
||||||
//! if shk.len() != Self::SHK_LEN {
|
|
||||||
//! return Err("shk does not have the correct length!".to_string());
|
|
||||||
//! }
|
|
||||||
//! if sk[0] != 42 {
|
|
||||||
//! return Err("Invalid public key!".to_string());
|
|
||||||
//! }
|
|
||||||
//! if ct[0] != 7 {
|
|
||||||
//! return Err("Invalid ciphertext!".to_string());
|
|
||||||
//! }
|
|
||||||
//! shk[0] = 17;
|
|
||||||
//! Ok(())
|
|
||||||
//! }
|
|
||||||
//! }
|
|
||||||
//! # use rosenpass_secret_memory::{secret_policy_use_only_malloc_secrets, Secret};
|
|
||||||
//! #
|
|
||||||
//! # type MyKem = DummyKem;
|
|
||||||
//! # secret_policy_use_only_malloc_secrets();
|
|
||||||
//! # let mut alice_sk: Secret<{ MyKem::SK_LEN }> = Secret::zero();
|
|
||||||
//! # let mut alice_pk: [u8; MyKem::PK_LEN] = [0; MyKem::PK_LEN];
|
|
||||||
//! # MyKem::keygen(alice_sk.secret_mut(), &mut alice_pk)?;
|
|
||||||
//!
|
|
||||||
//! # let mut bob_shk: Secret<{ MyKem::SHK_LEN }> = Secret::zero();
|
|
||||||
//! # let mut bob_ct: [u8; MyKem::CT_LEN] = [0; MyKem::CT_LEN];
|
|
||||||
//! # MyKem::encaps(bob_shk.secret_mut(), &mut bob_ct, &mut alice_pk)?;
|
|
||||||
//! #
|
|
||||||
//! # let mut alice_shk: Secret<{ MyKem::SHK_LEN }> = Secret::zero();
|
|
||||||
//! # MyKem::decaps(alice_shk.secret_mut(), alice_sk.secret_mut(), &mut bob_ct)?;
|
|
||||||
//! #
|
|
||||||
//! # assert_eq!(alice_shk.secret(), bob_shk.secret());
|
|
||||||
//! #
|
|
||||||
//! # Ok::<(), String>(())
|
|
||||||
//!```
|
|
||||||
//!
|
|
||||||
|
|
||||||
/// Key Encapsulation Mechanism
|
/// Key Encapsulation Mechanism
|
||||||
///
|
///
|
||||||
|
|||||||
@@ -1,5 +1,2 @@
|
|||||||
//! This trait contains traits, constants and wrappers that provid= the interface between Rosenpass
|
mod kem;
|
||||||
//! as a consumer of cryptographic libraries and the implementations of cryptographic algorithms.
|
pub use kem::Kem;
|
||||||
|
|
||||||
pub mod algorithms;
|
|
||||||
pub mod primitives;
|
|
||||||
|
|||||||
@@ -1,10 +0,0 @@
|
|||||||
//! Traits for cryptographic primitives used in Rosenpass, specifically KEM, AEAD and keyed
|
|
||||||
//! hashing.
|
|
||||||
|
|
||||||
pub(crate) mod aead;
|
|
||||||
pub(crate) mod kem;
|
|
||||||
pub(crate) mod keyed_hash;
|
|
||||||
|
|
||||||
pub use aead::{Aead, AeadWithNonceInCiphertext, Error as AeadError};
|
|
||||||
pub use kem::{Error as KemError, Kem};
|
|
||||||
pub use keyed_hash::*;
|
|
||||||
@@ -1,175 +0,0 @@
|
|||||||
use rosenpass_to::{ops::copy_slice, To as _};
|
|
||||||
use thiserror::Error;
|
|
||||||
|
|
||||||
/// Models authenticated encryption with assiciated data (AEAD) functionality.
|
|
||||||
///
|
|
||||||
/// The methods of this trait take a `&self` argument as a receiver. This has two reasons:
|
|
||||||
/// 1. It makes type inference a lot smoother
|
|
||||||
/// 2. It allows to use the functionality through a trait object or having an enum that has
|
|
||||||
/// variants for multiple options (like e.g. the `KeyedHash` enum in `rosenpass-ciphers`).
|
|
||||||
///
|
|
||||||
/// Since the caller needs an instance of the type to use the functionality, implementors are
|
|
||||||
/// adviced to implement the [`Default`] trait where possible.
|
|
||||||
///
|
|
||||||
/// Example for encrypting a message with a specific [`Aead`] instance:
|
|
||||||
/// ```
|
|
||||||
/// use rosenpass_cipher_traits::primitives::Aead;
|
|
||||||
///
|
|
||||||
/// const KEY_LEN: usize = 32;
|
|
||||||
/// const NONCE_LEN: usize = 12;
|
|
||||||
/// const TAG_LEN: usize = 16;
|
|
||||||
///
|
|
||||||
/// fn encrypt_message_given_an_aead<AeadImpl>(
|
|
||||||
/// aead: &AeadImpl,
|
|
||||||
/// msg: &str,
|
|
||||||
/// nonce: &[u8; NONCE_LEN],
|
|
||||||
/// encrypted: &mut [u8]
|
|
||||||
/// ) where AeadImpl: Aead<KEY_LEN, NONCE_LEN, TAG_LEN> {
|
|
||||||
/// let key = [0u8; KEY_LEN]; // This is not a secure key!
|
|
||||||
/// let ad = b""; // we don't need associated data here
|
|
||||||
/// aead.encrypt(encrypted, &key, nonce, ad, msg.as_bytes()).unwrap();
|
|
||||||
/// }
|
|
||||||
/// ```
|
|
||||||
///
|
|
||||||
/// If only the type (but no instance) is available, then we can still encrypt, as long as the type
|
|
||||||
/// also is [`Default`]:
|
|
||||||
/// ```
|
|
||||||
/// use rosenpass_cipher_traits::primitives::Aead;
|
|
||||||
///
|
|
||||||
/// const KEY_LEN: usize = 32;
|
|
||||||
/// const NONCE_LEN: usize = 12;
|
|
||||||
/// const TAG_LEN: usize = 16;
|
|
||||||
///
|
|
||||||
/// fn encrypt_message_without_aead<AeadImpl>(
|
|
||||||
/// msg: &str,
|
|
||||||
/// nonce: &[u8; NONCE_LEN],
|
|
||||||
/// encrypted: &mut [u8]
|
|
||||||
/// ) where AeadImpl: Default + Aead<KEY_LEN, NONCE_LEN, TAG_LEN> {
|
|
||||||
/// let key = [0u8; KEY_LEN]; // This is not a secure key!
|
|
||||||
/// let ad = b""; // we don't need associated data here
|
|
||||||
/// AeadImpl::default().encrypt(encrypted, &key, nonce, ad, msg.as_bytes()).unwrap();
|
|
||||||
/// }
|
|
||||||
/// ```
|
|
||||||
pub trait Aead<const KEY_LEN: usize, const NONCE_LEN: usize, const TAG_LEN: usize> {
|
|
||||||
const KEY_LEN: usize = KEY_LEN;
|
|
||||||
const NONCE_LEN: usize = NONCE_LEN;
|
|
||||||
const TAG_LEN: usize = TAG_LEN;
|
|
||||||
|
|
||||||
/// Encrypts `plaintext` using the given `key` and `nonce`, taking into account the additional
|
|
||||||
/// data `ad` and writes the result into `ciphertext`.
|
|
||||||
///
|
|
||||||
/// `ciphertext` must be exactly `TAG_LEN` longer than `plaintext`.
|
|
||||||
fn encrypt(
|
|
||||||
&self,
|
|
||||||
ciphertext: &mut [u8],
|
|
||||||
key: &[u8; KEY_LEN],
|
|
||||||
nonce: &[u8; NONCE_LEN],
|
|
||||||
ad: &[u8],
|
|
||||||
plaintext: &[u8],
|
|
||||||
) -> Result<(), Error>;
|
|
||||||
|
|
||||||
/// Decrypts `ciphertexttext` using the given `key` and `nonce`, taking into account the additional
|
|
||||||
/// data `ad` and writes the result into `plaintext`.
|
|
||||||
///
|
|
||||||
/// `ciphertext` must be exactly `TAG_LEN` longer than `plaintext`.
|
|
||||||
fn decrypt(
|
|
||||||
&self,
|
|
||||||
plaintext: &mut [u8],
|
|
||||||
key: &[u8; KEY_LEN],
|
|
||||||
nonce: &[u8; NONCE_LEN],
|
|
||||||
ad: &[u8],
|
|
||||||
ciphertext: &[u8],
|
|
||||||
) -> Result<(), Error>;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Provides an AEAD API where the nonce is part of the ciphertext.
|
|
||||||
///
|
|
||||||
/// The old xaead API had the ciphertext begin with the `nonce`. In order to not having to change
|
|
||||||
/// the calling code too much, we add a wrapper trait that provides this API and implement it for
|
|
||||||
/// all AEAD.
|
|
||||||
pub trait AeadWithNonceInCiphertext<
|
|
||||||
const KEY_LEN: usize,
|
|
||||||
const NONCE_LEN: usize,
|
|
||||||
const TAG_LEN: usize,
|
|
||||||
>: Aead<KEY_LEN, NONCE_LEN, TAG_LEN>
|
|
||||||
{
|
|
||||||
/// Encrypts `plaintext` using the given `key` and `nonce`, taking into account the additional
|
|
||||||
/// data `ad` and writes the result into `ciphertext`.
|
|
||||||
///
|
|
||||||
/// `ciphertext` must be exactly `TAG_LEN` + `NONCE_LEN` longer than `plaintext`.
|
|
||||||
fn encrypt_with_nonce_in_ctxt(
|
|
||||||
&self,
|
|
||||||
ciphertext: &mut [u8],
|
|
||||||
key: &[u8; KEY_LEN],
|
|
||||||
nonce: &[u8; NONCE_LEN],
|
|
||||||
ad: &[u8],
|
|
||||||
plaintext: &[u8],
|
|
||||||
) -> Result<(), Error> {
|
|
||||||
// The comparison looks complicated, but we need to do it this way to prevent
|
|
||||||
// over/underflows.
|
|
||||||
if ciphertext.len() < NONCE_LEN + TAG_LEN
|
|
||||||
|| ciphertext.len() - TAG_LEN - NONCE_LEN < plaintext.len()
|
|
||||||
{
|
|
||||||
return Err(Error::InvalidLengths);
|
|
||||||
}
|
|
||||||
|
|
||||||
let (n, rest) = ciphertext.split_at_mut(NONCE_LEN);
|
|
||||||
copy_slice(nonce).to(n);
|
|
||||||
|
|
||||||
self.encrypt(rest, key, nonce, ad, plaintext)
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Decrypts `ciphertexttext` using the given `key` and `nonce`, taking into account the additional
|
|
||||||
/// data `ad` and writes the result into `plaintext`.
|
|
||||||
///
|
|
||||||
/// `ciphertext` must be exactly `TAG_LEN` + `NONCE_LEN` longer than `plaintext`.
|
|
||||||
fn decrypt_with_nonce_in_ctxt(
|
|
||||||
&self,
|
|
||||||
plaintext: &mut [u8],
|
|
||||||
key: &[u8; KEY_LEN],
|
|
||||||
ad: &[u8],
|
|
||||||
ciphertext: &[u8],
|
|
||||||
) -> Result<(), Error> {
|
|
||||||
// The comparison looks complicated, but we need to do it this way to prevent
|
|
||||||
// over/underflows.
|
|
||||||
if ciphertext.len() < NONCE_LEN + TAG_LEN
|
|
||||||
|| ciphertext.len() - TAG_LEN - NONCE_LEN < plaintext.len()
|
|
||||||
{
|
|
||||||
return Err(Error::InvalidLengths);
|
|
||||||
}
|
|
||||||
|
|
||||||
let (nonce, rest) = ciphertext.split_at(NONCE_LEN);
|
|
||||||
// We know this should be the right length (we just split it), and everything else would be
|
|
||||||
// very unexpected.
|
|
||||||
let nonce = nonce.try_into().map_err(|_| Error::InternalError)?;
|
|
||||||
|
|
||||||
self.decrypt(plaintext, key, nonce, ad, rest)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<
|
|
||||||
const KEY_LEN: usize,
|
|
||||||
const NONCE_LEN: usize,
|
|
||||||
const TAG_LEN: usize,
|
|
||||||
T: Aead<KEY_LEN, NONCE_LEN, TAG_LEN>,
|
|
||||||
> AeadWithNonceInCiphertext<KEY_LEN, NONCE_LEN, TAG_LEN> for T
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
/// The error returned by AEAD operations
|
|
||||||
#[derive(Debug, Error)]
|
|
||||||
pub enum Error {
|
|
||||||
/// An internal error occurred. This should never be happen and indicates an error in the
|
|
||||||
/// AEAD implementation.
|
|
||||||
#[error("internal error")]
|
|
||||||
InternalError,
|
|
||||||
|
|
||||||
/// Could not decrypt a message because the message is not a valid ciphertext for the given
|
|
||||||
/// key.
|
|
||||||
#[error("decryption error")]
|
|
||||||
DecryptError,
|
|
||||||
|
|
||||||
/// The provided buffers have the wrong lengths.
|
|
||||||
#[error("buffers have invalid length")]
|
|
||||||
InvalidLengths,
|
|
||||||
}
|
|
||||||
@@ -1,212 +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:
|
|
||||||
//! [Kyber512](../../rosenpass_oqs/kyber_512/enum.Kyber512.html) and
|
|
||||||
//! [ClassicMceliece460896](../../rosenpass_oqs/classic_mceliece_460896/enum.ClassicMceliece460896.html).
|
|
||||||
//!
|
|
||||||
//! An example where Alice generates a keypair and gives her public key to Bob, for Bob to
|
|
||||||
//! encapsulate a symmetric key and Alice to decapsulate it would look as follows.
|
|
||||||
//! In the example, we are using Kyber512, but any KEM that correctly implements the [Kem]
|
|
||||||
//! trait could be used as well.
|
|
||||||
//!```rust
|
|
||||||
//! use rosenpass_cipher_traits::primitives::Kem;
|
|
||||||
//! use rosenpass_oqs::Kyber512;
|
|
||||||
//! # use rosenpass_secret_memory::{secret_policy_use_only_malloc_secrets, Secret};
|
|
||||||
//!
|
|
||||||
//! type MyKem = Kyber512;
|
|
||||||
//! secret_policy_use_only_malloc_secrets();
|
|
||||||
//! let mut alice_sk: Secret<{ MyKem::SK_LEN }> = Secret::zero();
|
|
||||||
//! let mut alice_pk: [u8; MyKem::PK_LEN] = [0; MyKem::PK_LEN];
|
|
||||||
//! MyKem::default().keygen(alice_sk.secret_mut(), &mut alice_pk)?;
|
|
||||||
//!
|
|
||||||
//! let mut bob_shk: Secret<{ MyKem::SHK_LEN }> = Secret::zero();
|
|
||||||
//! let mut bob_ct: [u8; MyKem::CT_LEN] = [0; MyKem::CT_LEN];
|
|
||||||
//! MyKem::default().encaps(bob_shk.secret_mut(), &mut bob_ct, &mut alice_pk)?;
|
|
||||||
//!
|
|
||||||
//! let mut alice_shk: Secret<{ MyKem::SHK_LEN }> = Secret::zero();
|
|
||||||
//! MyKem::default().decaps(alice_shk.secret_mut(), alice_sk.secret_mut(), &mut bob_ct)?;
|
|
||||||
//!
|
|
||||||
//! # assert_eq!(alice_shk.secret(), bob_shk.secret());
|
|
||||||
//! # Ok::<(), anyhow::Error>(())
|
|
||||||
//!```
|
|
||||||
//!
|
|
||||||
//! Implementing the [Kem]-trait for a KEM is easy. Mostly, you must format the KEM's
|
|
||||||
//! keys, and ciphertext as `u8` slices. Below, we provide an example for how the trait can
|
|
||||||
//! be implemented using a **HORRIBLY INSECURE** DummyKem that only uses static values for keys
|
|
||||||
//! and ciphertexts as an example.
|
|
||||||
//!```rust
|
|
||||||
//!# use rosenpass_cipher_traits::primitives::{Kem, KemError as Error};
|
|
||||||
//!
|
|
||||||
//! struct DummyKem {}
|
|
||||||
//! impl Kem<1,1,1,1> for DummyKem {
|
|
||||||
//!
|
|
||||||
//! // For this DummyKem, we will use a single `u8` for everything
|
|
||||||
//! const SK_LEN: usize = 1;
|
|
||||||
//! const PK_LEN: usize = 1;
|
|
||||||
//! const CT_LEN: usize = 1;
|
|
||||||
//! const SHK_LEN: usize = 1;
|
|
||||||
//!
|
|
||||||
//! fn keygen(&self, sk: &mut [u8;1], pk: &mut [u8;1]) -> Result<(), Error> {
|
|
||||||
//! sk[0] = 42;
|
|
||||||
//! pk[0] = 21;
|
|
||||||
//! Ok(())
|
|
||||||
//! }
|
|
||||||
//!
|
|
||||||
//! fn encaps(&self, shk: &mut [u8;1], ct: &mut [u8;1], pk: &[u8;1]) -> Result<(), Error> {
|
|
||||||
//! if pk[0] != 21 {
|
|
||||||
//! return Err(Error::InvalidArgument);
|
|
||||||
//! }
|
|
||||||
//! ct[0] = 7;
|
|
||||||
//! shk[0] = 17;
|
|
||||||
//! Ok(())
|
|
||||||
//! }
|
|
||||||
//!
|
|
||||||
//! fn decaps(&self, shk: &mut [u8;1 ], sk: &[u8;1], ct: &[u8;1]) -> Result<(), Error> {
|
|
||||||
//! if sk[0] != 42 {
|
|
||||||
//! return Err(Error::InvalidArgument);
|
|
||||||
//! }
|
|
||||||
//! if ct[0] != 7 {
|
|
||||||
//! return Err(Error::InvalidArgument);
|
|
||||||
//! }
|
|
||||||
//! shk[0] = 17;
|
|
||||||
//! Ok(())
|
|
||||||
//! }
|
|
||||||
//! }
|
|
||||||
//!
|
|
||||||
//! impl Default for DummyKem {
|
|
||||||
//! fn default() -> Self {
|
|
||||||
//! Self{}
|
|
||||||
//! }
|
|
||||||
//! }
|
|
||||||
//! # use rosenpass_secret_memory::{secret_policy_use_only_malloc_secrets, Secret};
|
|
||||||
//! #
|
|
||||||
//! # type MyKem = DummyKem;
|
|
||||||
//! # secret_policy_use_only_malloc_secrets();
|
|
||||||
//! # let mut alice_sk: Secret<{ MyKem::SK_LEN }> = Secret::zero();
|
|
||||||
//! # let mut alice_pk: [u8; MyKem::PK_LEN] = [0; MyKem::PK_LEN];
|
|
||||||
//! # MyKem::default().keygen(alice_sk.secret_mut(), &mut alice_pk)?;
|
|
||||||
//!
|
|
||||||
//! # let mut bob_shk: Secret<{ MyKem::SHK_LEN }> = Secret::zero();
|
|
||||||
//! # let mut bob_ct: [u8; MyKem::CT_LEN] = [0; MyKem::CT_LEN];
|
|
||||||
//! # MyKem::default().encaps(bob_shk.secret_mut(), &mut bob_ct, &mut alice_pk)?;
|
|
||||||
//! #
|
|
||||||
//! # let mut alice_shk: Secret<{ MyKem::SHK_LEN }> = Secret::zero();
|
|
||||||
//! # MyKem::default().decaps(alice_shk.secret_mut(), alice_sk.secret_mut(), &mut bob_ct)?;
|
|
||||||
//! #
|
|
||||||
//! # assert_eq!(alice_shk.secret(), bob_shk.secret());
|
|
||||||
//! #
|
|
||||||
//! # Ok::<(), Error>(())
|
|
||||||
//!```
|
|
||||||
//!
|
|
||||||
|
|
||||||
use thiserror::Error;
|
|
||||||
|
|
||||||
/// Key Encapsulation Mechanism
|
|
||||||
///
|
|
||||||
/// The KEM interface defines three operations: Key generation, key encapsulation and key
|
|
||||||
/// decapsulation. The parameters are made available as associated constants for convenience.
|
|
||||||
///
|
|
||||||
/// The methods of this trait take a `&self` argument as a receiver. This has two reasons:
|
|
||||||
/// 1. It makes type inference a lot smoother
|
|
||||||
/// 2. It allows to use the functionality through a trait object or having an enum that has
|
|
||||||
/// variants for multiple options (like e.g. the `KeyedHash` enum in `rosenpass-ciphers`).
|
|
||||||
///
|
|
||||||
/// Since the caller needs an instance of the type to use the functionality, implementors are
|
|
||||||
/// adviced to implement the [`Default`] trait where possible.
|
|
||||||
///
|
|
||||||
/// Example for encrypting a message with a specific [`Kem`] instance:
|
|
||||||
/// ```
|
|
||||||
/// use rosenpass_cipher_traits::primitives::Kem;
|
|
||||||
///
|
|
||||||
/// const SK_LEN: usize = 1632;
|
|
||||||
/// const PK_LEN: usize = 800;
|
|
||||||
/// const CT_LEN: usize = 768;
|
|
||||||
/// const SHK_LEN: usize = 32;
|
|
||||||
///
|
|
||||||
/// fn encaps_given_a_kem<KemImpl>(
|
|
||||||
/// kem: &KemImpl,
|
|
||||||
/// pk: &[u8; PK_LEN],
|
|
||||||
/// ct: &mut [u8; CT_LEN]
|
|
||||||
/// ) -> [u8; SHK_LEN] where KemImpl: Kem<SK_LEN, PK_LEN, CT_LEN, SHK_LEN>{
|
|
||||||
/// let mut shk = [0u8; SHK_LEN];
|
|
||||||
/// kem.encaps(&mut shk, ct, pk).unwrap();
|
|
||||||
/// shk
|
|
||||||
/// }
|
|
||||||
/// ```
|
|
||||||
///
|
|
||||||
/// If only the type (but no instance) is available, then we can still use the trait, as long as
|
|
||||||
/// the type also is [`Default`]:
|
|
||||||
/// ```
|
|
||||||
/// use rosenpass_cipher_traits::primitives::Kem;
|
|
||||||
///
|
|
||||||
/// const SK_LEN: usize = 1632;
|
|
||||||
/// const PK_LEN: usize = 800;
|
|
||||||
/// const CT_LEN: usize = 768;
|
|
||||||
/// const SHK_LEN: usize = 32;
|
|
||||||
///
|
|
||||||
/// fn encaps_without_kem<KemImpl>(
|
|
||||||
/// pk: &[u8; PK_LEN],
|
|
||||||
/// ct: &mut [u8; CT_LEN]
|
|
||||||
/// ) -> [u8; SHK_LEN]
|
|
||||||
/// where KemImpl: Default + Kem<SK_LEN, PK_LEN, CT_LEN, SHK_LEN> {
|
|
||||||
/// let mut shk = [0u8; SHK_LEN];
|
|
||||||
/// KemImpl::default().encaps(&mut shk, ct, pk).unwrap();
|
|
||||||
/// shk
|
|
||||||
/// }
|
|
||||||
/// ```
|
|
||||||
pub trait Kem<const SK_LEN: usize, const PK_LEN: usize, const CT_LEN: usize, const SHK_LEN: usize> {
|
|
||||||
/// The length of the secret (decapsulation) key.
|
|
||||||
const SK_LEN: usize = SK_LEN;
|
|
||||||
|
|
||||||
/// The length of the public (encapsulation) key.
|
|
||||||
const PK_LEN: usize = PK_LEN;
|
|
||||||
|
|
||||||
/// The length of the ciphertext.
|
|
||||||
const CT_LEN: usize = CT_LEN;
|
|
||||||
|
|
||||||
/// The legnth of the resulting shared key.
|
|
||||||
const SHK_LEN: usize = SHK_LEN;
|
|
||||||
|
|
||||||
/// Generate a keypair consisting of secret key (`sk`) and public key (`pk`)
|
|
||||||
///
|
|
||||||
/// `keygen() -> sk, pk`
|
|
||||||
fn keygen(&self, sk: &mut [u8; SK_LEN], pk: &mut [u8; PK_LEN]) -> Result<(), 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(
|
|
||||||
&self,
|
|
||||||
shk: &mut [u8; SHK_LEN],
|
|
||||||
ct: &mut [u8; CT_LEN],
|
|
||||||
pk: &[u8; PK_LEN],
|
|
||||||
) -> Result<(), Error>;
|
|
||||||
|
|
||||||
/// From a secret key (`sk`) and a cipher text (`ct`) derive a shared key
|
|
||||||
/// (`shk`)
|
|
||||||
///
|
|
||||||
/// `decaps(sk, ct) -> shk`
|
|
||||||
fn decaps(
|
|
||||||
&self,
|
|
||||||
shk: &mut [u8; SHK_LEN],
|
|
||||||
sk: &[u8; SK_LEN],
|
|
||||||
ct: &[u8; CT_LEN],
|
|
||||||
) -> Result<(), Error>;
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug, Error)]
|
|
||||||
pub enum Error {
|
|
||||||
#[error("invalid argument")]
|
|
||||||
InvalidArgument,
|
|
||||||
#[error("internal error")]
|
|
||||||
InternalError,
|
|
||||||
}
|
|
||||||
@@ -1,159 +0,0 @@
|
|||||||
use std::marker::PhantomData;
|
|
||||||
|
|
||||||
/// Models a keyed hash function using an associated function (i.e. without `&self` receiver).
|
|
||||||
pub trait KeyedHash<const KEY_LEN: usize, const HASH_LEN: usize> {
|
|
||||||
/// The error type used to signal what went wrong.
|
|
||||||
type Error;
|
|
||||||
|
|
||||||
/// Performs a keyed hash using `key` and `data` and writes the output to `out`
|
|
||||||
fn keyed_hash(
|
|
||||||
key: &[u8; KEY_LEN],
|
|
||||||
data: &[u8],
|
|
||||||
out: &mut [u8; HASH_LEN],
|
|
||||||
) -> Result<(), Self::Error>;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Models a keyed hash function using a method (i.e. with a `&self` receiver).
|
|
||||||
///
|
|
||||||
/// This makes type inference easier, but also requires having a [`KeyedHashInstance`] value,
|
|
||||||
/// instead of just the [`KeyedHash`] type.
|
|
||||||
pub trait KeyedHashInstance<const KEY_LEN: usize, const HASH_LEN: usize> {
|
|
||||||
/// The error type used to signal what went wrong.
|
|
||||||
type Error;
|
|
||||||
|
|
||||||
/// Performs a keyed hash using `key` and `data` and writes the output to `out`
|
|
||||||
fn keyed_hash(
|
|
||||||
&self,
|
|
||||||
key: &[u8; KEY_LEN],
|
|
||||||
data: &[u8],
|
|
||||||
out: &mut [u8; HASH_LEN],
|
|
||||||
) -> Result<(), Self::Error>;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// This is a helper to allow for type parameter inference when calling functions
|
|
||||||
/// that need a [KeyedHash].
|
|
||||||
///
|
|
||||||
/// Really just binds the [KeyedHash] trait to a dummy variable, so the type of this dummy variable
|
|
||||||
/// can be used for type inference. Less typing work.
|
|
||||||
#[derive(Debug, PartialEq, Eq)]
|
|
||||||
pub struct InferKeyedHash<Static, const KEY_LEN: usize, const HASH_LEN: usize>
|
|
||||||
where
|
|
||||||
Static: KeyedHash<KEY_LEN, HASH_LEN>,
|
|
||||||
{
|
|
||||||
pub _phantom_keyed_hasher: PhantomData<Static>,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<Static, const KEY_LEN: usize, const HASH_LEN: usize> InferKeyedHash<Static, KEY_LEN, HASH_LEN>
|
|
||||||
where
|
|
||||||
Static: KeyedHash<KEY_LEN, HASH_LEN>,
|
|
||||||
{
|
|
||||||
pub const KEY_LEN: usize = KEY_LEN;
|
|
||||||
pub const HASH_LEN: usize = HASH_LEN;
|
|
||||||
|
|
||||||
pub const fn new() -> Self {
|
|
||||||
Self {
|
|
||||||
_phantom_keyed_hasher: PhantomData,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// This just forwards to [KeyedHash::keyed_hash] of the type parameter `Static`
|
|
||||||
fn keyed_hash_internal<'a>(
|
|
||||||
&self,
|
|
||||||
key: &'a [u8; KEY_LEN],
|
|
||||||
data: &'a [u8],
|
|
||||||
out: &mut [u8; HASH_LEN],
|
|
||||||
) -> Result<(), Static::Error> {
|
|
||||||
Static::keyed_hash(key, data, out)
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Returns the key length of the keyed hash function.
|
|
||||||
pub const fn key_len(self) -> usize {
|
|
||||||
Self::KEY_LEN
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Returns the hash length of the keyed hash function.
|
|
||||||
pub const fn hash_len(self) -> usize {
|
|
||||||
Self::HASH_LEN
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<const KEY_LEN: usize, const HASH_LEN: usize, Static: KeyedHash<KEY_LEN, HASH_LEN>>
|
|
||||||
KeyedHashInstance<KEY_LEN, HASH_LEN> for InferKeyedHash<Static, KEY_LEN, HASH_LEN>
|
|
||||||
{
|
|
||||||
type Error = Static::Error;
|
|
||||||
|
|
||||||
fn keyed_hash(
|
|
||||||
&self,
|
|
||||||
key: &[u8; KEY_LEN],
|
|
||||||
data: &[u8],
|
|
||||||
out: &mut [u8; HASH_LEN],
|
|
||||||
) -> Result<(), Static::Error> {
|
|
||||||
self.keyed_hash_internal(key, data, out)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Helper traits /////////////////////////////////////////////
|
|
||||||
|
|
||||||
impl<Static, const KEY_LEN: usize, const OUT_LEN: usize> Default
|
|
||||||
for InferKeyedHash<Static, KEY_LEN, OUT_LEN>
|
|
||||||
where
|
|
||||||
Static: KeyedHash<KEY_LEN, OUT_LEN>,
|
|
||||||
{
|
|
||||||
fn default() -> Self {
|
|
||||||
Self::new()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<Static, const KEY_LEN: usize, const OUT_LEN: usize> Clone
|
|
||||||
for InferKeyedHash<Static, KEY_LEN, OUT_LEN>
|
|
||||||
where
|
|
||||||
Static: KeyedHash<KEY_LEN, OUT_LEN>,
|
|
||||||
{
|
|
||||||
fn clone(&self) -> Self {
|
|
||||||
*self
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<Static, const KEY_LEN: usize, const OUT_LEN: usize> Copy
|
|
||||||
for InferKeyedHash<Static, KEY_LEN, OUT_LEN>
|
|
||||||
where
|
|
||||||
Static: KeyedHash<KEY_LEN, OUT_LEN>,
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
use rosenpass_to::{with_destination, To};
|
|
||||||
|
|
||||||
/// Extends the [`KeyedHash`] trait with a [`To`]-flavoured function.
|
|
||||||
pub trait KeyedHashTo<const KEY_LEN: usize, const HASH_LEN: usize>:
|
|
||||||
KeyedHash<KEY_LEN, HASH_LEN>
|
|
||||||
{
|
|
||||||
fn keyed_hash_to(
|
|
||||||
key: &[u8; KEY_LEN],
|
|
||||||
data: &[u8],
|
|
||||||
) -> impl To<[u8; HASH_LEN], Result<(), Self::Error>> {
|
|
||||||
with_destination(|out| Self::keyed_hash(key, data, out))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<const KEY_LEN: usize, const HASH_LEN: usize, T: KeyedHash<KEY_LEN, HASH_LEN>>
|
|
||||||
KeyedHashTo<KEY_LEN, HASH_LEN> for T
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Extends the [`KeyedHashInstance`] trait with a [`To`]-flavoured function.
|
|
||||||
pub trait KeyedHashInstanceTo<const KEY_LEN: usize, const HASH_LEN: usize>:
|
|
||||||
KeyedHashInstance<KEY_LEN, HASH_LEN>
|
|
||||||
{
|
|
||||||
fn keyed_hash_to(
|
|
||||||
&self,
|
|
||||||
key: &[u8; KEY_LEN],
|
|
||||||
data: &[u8],
|
|
||||||
) -> impl To<[u8; HASH_LEN], Result<(), Self::Error>> {
|
|
||||||
with_destination(|out| self.keyed_hash(key, data, out))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<const KEY_LEN: usize, const HASH_LEN: usize, T: KeyedHashInstance<KEY_LEN, HASH_LEN>>
|
|
||||||
KeyedHashInstanceTo<KEY_LEN, HASH_LEN> for T
|
|
||||||
{
|
|
||||||
}
|
|
||||||
@@ -8,42 +8,9 @@ description = "Rosenpass internal ciphers and other cryptographic primitives use
|
|||||||
homepage = "https://rosenpass.eu/"
|
homepage = "https://rosenpass.eu/"
|
||||||
repository = "https://github.com/rosenpass/rosenpass"
|
repository = "https://github.com/rosenpass/rosenpass"
|
||||||
readme = "readme.md"
|
readme = "readme.md"
|
||||||
rust-version = "1.77.0"
|
|
||||||
|
|
||||||
[features]
|
[features]
|
||||||
# whether the types should be defined
|
experiment_libcrux = ["dep:libcrux"]
|
||||||
experiment_libcrux_define_blake2 = ["dep:libcrux-blake2", "dep:thiserror"]
|
|
||||||
experiment_libcrux_define_kyber = ["dep:libcrux-ml-kem", "dep:rand"]
|
|
||||||
experiment_libcrux_define_chachapoly = ["dep:libcrux-chacha20poly1305"]
|
|
||||||
|
|
||||||
# whether the types should be used by default
|
|
||||||
experiment_libcrux_blake2 = ["experiment_libcrux_define_blake2"]
|
|
||||||
experiment_libcrux_kyber = ["experiment_libcrux_define_kyber"]
|
|
||||||
experiment_libcrux_chachapoly = ["experiment_libcrux_define_chachapoly"]
|
|
||||||
experiment_libcrux_chachapoly_test = [
|
|
||||||
"experiment_libcrux_define_chachapoly",
|
|
||||||
"dep:libcrux",
|
|
||||||
]
|
|
||||||
|
|
||||||
# shorthands
|
|
||||||
experiment_libcrux_define_all = [
|
|
||||||
"experiment_libcrux_define_blake2",
|
|
||||||
"experiment_libcrux_define_chachapoly",
|
|
||||||
"experiment_libcrux_define_kyber",
|
|
||||||
]
|
|
||||||
experiment_libcrux_all = [
|
|
||||||
"experiment_libcrux_blake2",
|
|
||||||
"experiment_libcrux_chachapoly",
|
|
||||||
"experiment_libcrux_chachapoly_test",
|
|
||||||
"experiment_libcrux_kyber",
|
|
||||||
]
|
|
||||||
|
|
||||||
bench = ["experiment_libcrux_define_all"]
|
|
||||||
|
|
||||||
[[bench]]
|
|
||||||
name = "primitives"
|
|
||||||
harness = false
|
|
||||||
required-features = ["bench"]
|
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
anyhow = { workspace = true }
|
anyhow = { workspace = true }
|
||||||
@@ -52,22 +19,8 @@ rosenpass-constant-time = { workspace = true }
|
|||||||
rosenpass-secret-memory = { workspace = true }
|
rosenpass-secret-memory = { workspace = true }
|
||||||
rosenpass-oqs = { workspace = true }
|
rosenpass-oqs = { workspace = true }
|
||||||
rosenpass-util = { workspace = true }
|
rosenpass-util = { workspace = true }
|
||||||
rosenpass-cipher-traits = { workspace = true }
|
|
||||||
static_assertions = { workspace = true }
|
static_assertions = { workspace = true }
|
||||||
zeroize = { workspace = true }
|
zeroize = { workspace = true }
|
||||||
chacha20poly1305 = { workspace = true }
|
chacha20poly1305 = { workspace = true }
|
||||||
blake2 = { workspace = true }
|
blake2 = { workspace = true }
|
||||||
sha3 = { workspace = true }
|
|
||||||
rand = { workspace = true, optional = true }
|
|
||||||
thiserror = { workspace = true, optional = true }
|
|
||||||
|
|
||||||
libcrux-chacha20poly1305 = { workspace = true, optional = true }
|
|
||||||
libcrux-blake2 = { workspace = true, optional = true }
|
|
||||||
libcrux-ml-kem = { workspace = true, optional = true, features = ["kyber"] }
|
|
||||||
|
|
||||||
# this one is only used in testing, so it requires the `experiment_libcrux_chachapoly_test` feature.
|
|
||||||
libcrux = { workspace = true, optional = true }
|
libcrux = { workspace = true, optional = true }
|
||||||
|
|
||||||
[dev-dependencies]
|
|
||||||
rand = { workspace = true }
|
|
||||||
criterion = { workspace = true }
|
|
||||||
|
|||||||
@@ -1,378 +0,0 @@
|
|||||||
criterion::criterion_main!(keyed_hash::benches, aead::benches, kem::benches);
|
|
||||||
|
|
||||||
fn benchid(base: KvPairs, last: KvPairs) -> String {
|
|
||||||
format!("{base},{last}")
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Clone, Copy, Debug)]
|
|
||||||
struct KvPair<'a>(&'a str, &'a str);
|
|
||||||
|
|
||||||
impl std::fmt::Display for KvPair<'_> {
|
|
||||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
|
||||||
write!(f, "{k}={v}", k = self.0, v = self.1)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Clone, Copy, Debug)]
|
|
||||||
struct KvPairs<'a>(&'a [KvPair<'a>]);
|
|
||||||
|
|
||||||
impl std::fmt::Display for KvPairs<'_> {
|
|
||||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
|
||||||
match self.0.len() {
|
|
||||||
0 => Ok(()),
|
|
||||||
1 => write!(f, "{}", &self.0[0]),
|
|
||||||
_ => {
|
|
||||||
let mut delim = "";
|
|
||||||
for pair in self.0 {
|
|
||||||
write!(f, "{delim}{pair}")?;
|
|
||||||
delim = ",";
|
|
||||||
}
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
mod kem {
|
|
||||||
criterion::criterion_group!(
|
|
||||||
benches,
|
|
||||||
bench_kyber512_libcrux,
|
|
||||||
bench_kyber512_oqs,
|
|
||||||
bench_classicmceliece460896_oqs
|
|
||||||
);
|
|
||||||
|
|
||||||
use criterion::Criterion;
|
|
||||||
|
|
||||||
fn bench_classicmceliece460896_oqs(c: &mut Criterion) {
|
|
||||||
template(
|
|
||||||
c,
|
|
||||||
"classicmceliece460896",
|
|
||||||
"oqs",
|
|
||||||
rosenpass_oqs::ClassicMceliece460896,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
fn bench_kyber512_libcrux(c: &mut Criterion) {
|
|
||||||
template(
|
|
||||||
c,
|
|
||||||
"kyber512",
|
|
||||||
"libcrux",
|
|
||||||
rosenpass_ciphers::subtle::libcrux::kyber512::Kyber512,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
fn bench_kyber512_oqs(c: &mut Criterion) {
|
|
||||||
template(c, "kyber512", "oqs", rosenpass_oqs::Kyber512);
|
|
||||||
}
|
|
||||||
|
|
||||||
use rosenpass_cipher_traits::primitives::Kem;
|
|
||||||
|
|
||||||
fn template<
|
|
||||||
const SK_LEN: usize,
|
|
||||||
const PK_LEN: usize,
|
|
||||||
const CT_LEN: usize,
|
|
||||||
const SHK_LEN: usize,
|
|
||||||
T: Kem<SK_LEN, PK_LEN, CT_LEN, SHK_LEN>,
|
|
||||||
>(
|
|
||||||
c: &mut Criterion,
|
|
||||||
alg_name: &str,
|
|
||||||
impl_name: &str,
|
|
||||||
scheme: T,
|
|
||||||
) {
|
|
||||||
use super::{benchid, KvPair, KvPairs};
|
|
||||||
|
|
||||||
let base = [
|
|
||||||
KvPair("primitive", "kem"),
|
|
||||||
KvPair("algorithm", alg_name),
|
|
||||||
KvPair("implementation", impl_name),
|
|
||||||
KvPair("length", "-1"),
|
|
||||||
];
|
|
||||||
|
|
||||||
let kem_benchid = |op| benchid(KvPairs(&base), KvPairs(&[KvPair("operation", op)]));
|
|
||||||
|
|
||||||
c.bench_function(&kem_benchid("keygen"), |bench| {
|
|
||||||
let mut sk = [0; SK_LEN];
|
|
||||||
let mut pk = [0; PK_LEN];
|
|
||||||
|
|
||||||
bench.iter(|| {
|
|
||||||
scheme.keygen(&mut sk, &mut pk).unwrap();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
c.bench_function(&kem_benchid("encaps"), |bench| {
|
|
||||||
let mut sk = [0; SK_LEN];
|
|
||||||
let mut pk = [0; PK_LEN];
|
|
||||||
let mut ct = [0; CT_LEN];
|
|
||||||
let mut shk = [0; SHK_LEN];
|
|
||||||
|
|
||||||
scheme.keygen(&mut sk, &mut pk).unwrap();
|
|
||||||
|
|
||||||
bench.iter(|| {
|
|
||||||
scheme.encaps(&mut shk, &mut ct, &pk).unwrap();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
c.bench_function(&kem_benchid("decaps"), |bench| {
|
|
||||||
let mut sk = [0; SK_LEN];
|
|
||||||
let mut pk = [0; PK_LEN];
|
|
||||||
let mut ct = [0; CT_LEN];
|
|
||||||
let mut shk = [0; SHK_LEN];
|
|
||||||
let mut shk2 = [0; SHK_LEN];
|
|
||||||
|
|
||||||
scheme.keygen(&mut sk, &mut pk).unwrap();
|
|
||||||
scheme.encaps(&mut shk, &mut ct, &pk).unwrap();
|
|
||||||
|
|
||||||
bench.iter(|| {
|
|
||||||
scheme.decaps(&mut shk2, &sk, &ct).unwrap();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
mod aead {
|
|
||||||
criterion::criterion_group!(
|
|
||||||
benches,
|
|
||||||
bench_chachapoly_libcrux,
|
|
||||||
bench_chachapoly_rustcrypto,
|
|
||||||
bench_xchachapoly_rustcrypto,
|
|
||||||
);
|
|
||||||
|
|
||||||
use criterion::Criterion;
|
|
||||||
|
|
||||||
const KEY_LEN: usize = rosenpass_ciphers::Aead::KEY_LEN;
|
|
||||||
const TAG_LEN: usize = rosenpass_ciphers::Aead::TAG_LEN;
|
|
||||||
|
|
||||||
fn bench_xchachapoly_rustcrypto(c: &mut Criterion) {
|
|
||||||
template(
|
|
||||||
c,
|
|
||||||
"xchacha20poly1305",
|
|
||||||
"rustcrypto",
|
|
||||||
rosenpass_ciphers::subtle::rust_crypto::xchacha20poly1305_ietf::XChaCha20Poly1305,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
fn bench_chachapoly_rustcrypto(c: &mut Criterion) {
|
|
||||||
template(
|
|
||||||
c,
|
|
||||||
"chacha20poly1305",
|
|
||||||
"rustcrypto",
|
|
||||||
rosenpass_ciphers::subtle::rust_crypto::chacha20poly1305_ietf::ChaCha20Poly1305,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
fn bench_chachapoly_libcrux(c: &mut Criterion) {
|
|
||||||
template(
|
|
||||||
c,
|
|
||||||
"chacha20poly1305",
|
|
||||||
"libcrux",
|
|
||||||
rosenpass_ciphers::subtle::libcrux::chacha20poly1305_ietf::ChaCha20Poly1305,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
use rosenpass_cipher_traits::primitives::Aead;
|
|
||||||
|
|
||||||
fn template<const NONCE_LEN: usize, T: Aead<KEY_LEN, NONCE_LEN, TAG_LEN>>(
|
|
||||||
c: &mut Criterion,
|
|
||||||
alg_name: &str,
|
|
||||||
impl_name: &str,
|
|
||||||
scheme: T,
|
|
||||||
) {
|
|
||||||
use crate::{benchid, KvPair, KvPairs};
|
|
||||||
|
|
||||||
let base = [
|
|
||||||
KvPair("primitive", "aead"),
|
|
||||||
KvPair("algorithm", alg_name),
|
|
||||||
KvPair("implementation", impl_name),
|
|
||||||
];
|
|
||||||
let aead_benchid = |op, len| {
|
|
||||||
benchid(
|
|
||||||
KvPairs(&base),
|
|
||||||
KvPairs(&[KvPair("operation", op), KvPair("length", len)]),
|
|
||||||
)
|
|
||||||
};
|
|
||||||
|
|
||||||
let key = [12; KEY_LEN];
|
|
||||||
let nonce = [23; NONCE_LEN];
|
|
||||||
let ad = [];
|
|
||||||
|
|
||||||
c.bench_function(&aead_benchid("encrypt", "0byte"), |bench| {
|
|
||||||
const DATA_LEN: usize = 0;
|
|
||||||
|
|
||||||
let ptxt = [];
|
|
||||||
let mut ctxt = [0; DATA_LEN + TAG_LEN];
|
|
||||||
|
|
||||||
bench.iter(|| {
|
|
||||||
scheme.encrypt(&mut ctxt, &key, &nonce, &ad, &ptxt).unwrap();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
c.bench_function(&aead_benchid("decrypt", "0byte"), |bench| {
|
|
||||||
const DATA_LEN: usize = 0;
|
|
||||||
|
|
||||||
let ptxt = [];
|
|
||||||
let mut ctxt = [0; DATA_LEN + TAG_LEN];
|
|
||||||
let mut ptxt_out = [0u8; DATA_LEN];
|
|
||||||
|
|
||||||
scheme.encrypt(&mut ctxt, &key, &nonce, &ad, &ptxt).unwrap();
|
|
||||||
|
|
||||||
bench.iter(|| {
|
|
||||||
scheme
|
|
||||||
.decrypt(&mut ptxt_out, &key, &nonce, &ad, &mut ctxt)
|
|
||||||
.unwrap()
|
|
||||||
})
|
|
||||||
});
|
|
||||||
|
|
||||||
c.bench_function(&aead_benchid("encrypt", "32byte"), |bench| {
|
|
||||||
const DATA_LEN: usize = 32;
|
|
||||||
|
|
||||||
let ptxt = [34u8; DATA_LEN];
|
|
||||||
let mut ctxt = [0; DATA_LEN + TAG_LEN];
|
|
||||||
|
|
||||||
bench.iter(|| {
|
|
||||||
scheme.encrypt(&mut ctxt, &key, &nonce, &ad, &ptxt).unwrap();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
c.bench_function(&aead_benchid("decrypt", "32byte"), |bench| {
|
|
||||||
const DATA_LEN: usize = 32;
|
|
||||||
|
|
||||||
let ptxt = [34u8; DATA_LEN];
|
|
||||||
let mut ctxt = [0; DATA_LEN + TAG_LEN];
|
|
||||||
let mut ptxt_out = [0u8; DATA_LEN];
|
|
||||||
|
|
||||||
scheme.encrypt(&mut ctxt, &key, &nonce, &ad, &ptxt).unwrap();
|
|
||||||
|
|
||||||
bench.iter(|| {
|
|
||||||
scheme
|
|
||||||
.decrypt(&mut ptxt_out, &key, &nonce, &ad, &mut ctxt)
|
|
||||||
.unwrap()
|
|
||||||
})
|
|
||||||
});
|
|
||||||
|
|
||||||
c.bench_function(&aead_benchid("encrypt", "1024byte"), |bench| {
|
|
||||||
const DATA_LEN: usize = 1024;
|
|
||||||
|
|
||||||
let ptxt = [34u8; DATA_LEN];
|
|
||||||
let mut ctxt = [0; DATA_LEN + TAG_LEN];
|
|
||||||
|
|
||||||
bench.iter(|| {
|
|
||||||
scheme.encrypt(&mut ctxt, &key, &nonce, &ad, &ptxt).unwrap();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
c.bench_function(&aead_benchid("decrypt", "1024byte"), |bench| {
|
|
||||||
const DATA_LEN: usize = 1024;
|
|
||||||
|
|
||||||
let ptxt = [34u8; DATA_LEN];
|
|
||||||
let mut ctxt = [0; DATA_LEN + TAG_LEN];
|
|
||||||
let mut ptxt_out = [0u8; DATA_LEN];
|
|
||||||
|
|
||||||
scheme.encrypt(&mut ctxt, &key, &nonce, &ad, &ptxt).unwrap();
|
|
||||||
|
|
||||||
bench.iter(|| {
|
|
||||||
scheme
|
|
||||||
.decrypt(&mut ptxt_out, &key, &nonce, &ad, &mut ctxt)
|
|
||||||
.unwrap()
|
|
||||||
})
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
mod keyed_hash {
|
|
||||||
criterion::criterion_group!(
|
|
||||||
benches,
|
|
||||||
bench_blake2b_rustcrypto,
|
|
||||||
bench_blake2b_libcrux,
|
|
||||||
bench_shake256_rustcrypto,
|
|
||||||
);
|
|
||||||
|
|
||||||
const KEY_LEN: usize = 32;
|
|
||||||
const HASH_LEN: usize = 32;
|
|
||||||
|
|
||||||
use criterion::Criterion;
|
|
||||||
|
|
||||||
fn bench_shake256_rustcrypto(c: &mut Criterion) {
|
|
||||||
template(
|
|
||||||
c,
|
|
||||||
"shake256",
|
|
||||||
"rustcrypto",
|
|
||||||
&rosenpass_ciphers::subtle::rust_crypto::keyed_shake256::SHAKE256Core,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
fn bench_blake2b_rustcrypto(c: &mut Criterion) {
|
|
||||||
template(
|
|
||||||
c,
|
|
||||||
"blake2b",
|
|
||||||
"rustcrypto",
|
|
||||||
&rosenpass_ciphers::subtle::rust_crypto::blake2b::Blake2b,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
fn bench_blake2b_libcrux(c: &mut Criterion) {
|
|
||||||
template(
|
|
||||||
c,
|
|
||||||
"blake2b",
|
|
||||||
"libcrux",
|
|
||||||
&rosenpass_ciphers::subtle::libcrux::blake2b::Blake2b,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
use rosenpass_cipher_traits::primitives::KeyedHash;
|
|
||||||
|
|
||||||
fn template<H: KeyedHash<KEY_LEN, HASH_LEN>>(
|
|
||||||
c: &mut Criterion,
|
|
||||||
alg_name: &str,
|
|
||||||
impl_name: &str,
|
|
||||||
_: &H,
|
|
||||||
) where
|
|
||||||
H::Error: std::fmt::Debug,
|
|
||||||
{
|
|
||||||
use crate::{benchid, KvPair, KvPairs};
|
|
||||||
|
|
||||||
let key = [12u8; KEY_LEN];
|
|
||||||
let mut out = [0u8; HASH_LEN];
|
|
||||||
|
|
||||||
let base = [
|
|
||||||
KvPair("primitive", "keyedhash"),
|
|
||||||
KvPair("algorithm", alg_name),
|
|
||||||
KvPair("implementation", impl_name),
|
|
||||||
KvPair("operation", "hash"),
|
|
||||||
];
|
|
||||||
let keyedhash_benchid = |len| benchid(KvPairs(&base), KvPairs(&[KvPair("length", len)]));
|
|
||||||
|
|
||||||
c.bench_function(&keyedhash_benchid("0byte"), |bench| {
|
|
||||||
let bytes = [];
|
|
||||||
|
|
||||||
bench.iter(|| {
|
|
||||||
H::keyed_hash(&key, &bytes, &mut out).unwrap();
|
|
||||||
})
|
|
||||||
})
|
|
||||||
.bench_function(&keyedhash_benchid("32byte"), |bench| {
|
|
||||||
let bytes = [34u8; 32];
|
|
||||||
|
|
||||||
bench.iter(|| {
|
|
||||||
H::keyed_hash(&key, &bytes, &mut out).unwrap();
|
|
||||||
})
|
|
||||||
})
|
|
||||||
.bench_function(&keyedhash_benchid("64byte"), |bench| {
|
|
||||||
let bytes = [34u8; 64];
|
|
||||||
|
|
||||||
bench.iter(|| {
|
|
||||||
H::keyed_hash(&key, &bytes, &mut out).unwrap();
|
|
||||||
})
|
|
||||||
})
|
|
||||||
.bench_function(&keyedhash_benchid("128byte"), |bench| {
|
|
||||||
let bytes = [34u8; 128];
|
|
||||||
|
|
||||||
bench.iter(|| {
|
|
||||||
H::keyed_hash(&key, &bytes, &mut out).unwrap();
|
|
||||||
})
|
|
||||||
})
|
|
||||||
.bench_function(&keyedhash_benchid("1024byte"), |bench| {
|
|
||||||
let bytes = [34u8; 1024];
|
|
||||||
|
|
||||||
bench.iter(|| {
|
|
||||||
H::keyed_hash(&key, &bytes, &mut out).unwrap();
|
|
||||||
})
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,276 +1,109 @@
|
|||||||
//!
|
|
||||||
//!```rust
|
|
||||||
//! # use rosenpass_ciphers::hash_domain::{HashDomain, HashDomainNamespace, SecretHashDomain, SecretHashDomainNamespace};
|
|
||||||
//! use rosenpass_ciphers::KeyedHash;
|
|
||||||
//! use rosenpass_secret_memory::Secret;
|
|
||||||
//! # rosenpass_secret_memory::secret_policy_use_only_malloc_secrets();
|
|
||||||
//!
|
|
||||||
//! const PROTOCOL_IDENTIFIER: &str = "MY_PROTOCOL:IDENTIFIER";
|
|
||||||
//! // create use once hash domain for the protocol identifier
|
|
||||||
//! let mut hash_domain = HashDomain::zero(KeyedHash::keyed_shake256());
|
|
||||||
//! 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::<(), anyhow::Error>(())
|
|
||||||
//!```
|
|
||||||
//!
|
|
||||||
|
|
||||||
use anyhow::Result;
|
use anyhow::Result;
|
||||||
use rosenpass_secret_memory::Secret;
|
use rosenpass_secret_memory::Secret;
|
||||||
use rosenpass_to::To as _;
|
use rosenpass_to::To;
|
||||||
|
|
||||||
pub use crate::{KeyedHash, KEY_LEN};
|
use crate::subtle::incorrect_hmac_blake2b as hash;
|
||||||
|
|
||||||
use rosenpass_cipher_traits::primitives::KeyedHashInstanceTo;
|
pub use hash::KEY_LEN;
|
||||||
|
|
||||||
// TODO Use a proper Dec interface
|
// 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)]
|
#[derive(Clone, Debug)]
|
||||||
pub struct HashDomain([u8; KEY_LEN], KeyedHash);
|
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)]
|
#[derive(Clone, Debug)]
|
||||||
pub struct HashDomainNamespace([u8; KEY_LEN], KeyedHash);
|
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)]
|
#[derive(Clone, Debug)]
|
||||||
pub struct SecretHashDomain(Secret<KEY_LEN>, KeyedHash);
|
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)]
|
#[derive(Clone, Debug)]
|
||||||
pub struct SecretHashDomainNamespace(Secret<KEY_LEN>, KeyedHash);
|
pub struct SecretHashDomainNamespace(Secret<KEY_LEN>);
|
||||||
|
|
||||||
impl HashDomain {
|
impl HashDomain {
|
||||||
/// Creates a nw [HashDomain] initialized with a all-zeros key.
|
pub fn zero() -> Self {
|
||||||
pub fn zero(choice: KeyedHash) -> Self {
|
Self([0u8; KEY_LEN])
|
||||||
Self([0u8; KEY_LEN], choice)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Turns this [HashDomain] into a [HashDomainNamespace], keeping the key.
|
|
||||||
pub fn dup(self) -> HashDomainNamespace {
|
pub fn dup(self) -> HashDomainNamespace {
|
||||||
HashDomainNamespace(self.0, self.1)
|
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 {
|
pub fn turn_secret(self) -> SecretHashDomain {
|
||||||
SecretHashDomain(Secret::from_slice(&self.0), self.1)
|
SecretHashDomain(Secret::from_slice(&self.0))
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: Protocol! Use domain separation to ensure that
|
// 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> {
|
pub fn mix(self, v: &[u8]) -> Result<Self> {
|
||||||
let mut new_key: [u8; KEY_LEN] = [0u8; KEY_LEN];
|
Ok(Self(hash::hash(&self.0, v).collect::<[u8; KEY_LEN]>()?))
|
||||||
self.1.keyed_hash_to(&self.0, v).to(&mut new_key)?;
|
|
||||||
Ok(Self(new_key, self.1))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Version of [Self::mix] that accepts an iterator and mixes all values from the iterator into
|
|
||||||
/// this hash domain.
|
|
||||||
///
|
|
||||||
/// # Examples
|
|
||||||
///
|
|
||||||
/// ```rust
|
|
||||||
/// use rosenpass_ciphers::{hash_domain::HashDomain, KeyedHash};
|
|
||||||
///
|
|
||||||
/// let hasher = HashDomain::zero(KeyedHash::keyed_shake256());
|
|
||||||
/// assert_eq!(
|
|
||||||
/// hasher.clone().mix(b"Hello")?.mix(b"World")?.into_value(),
|
|
||||||
/// hasher.clone().mix_many([b"Hello", b"World"])?.into_value()
|
|
||||||
/// );
|
|
||||||
///
|
|
||||||
/// Ok::<(), anyhow::Error>(())
|
|
||||||
/// ```
|
|
||||||
pub fn mix_many<I, T>(mut self, it: I) -> Result<Self>
|
|
||||||
where
|
|
||||||
I: IntoIterator<Item = T>,
|
|
||||||
T: AsRef<[u8]>,
|
|
||||||
{
|
|
||||||
for e in it {
|
|
||||||
self = self.mix(e.as_ref())?;
|
|
||||||
}
|
|
||||||
Ok(self)
|
|
||||||
}
|
|
||||||
|
|
||||||
/// 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> {
|
pub fn mix_secret<const N: usize>(self, v: Secret<N>) -> Result<SecretHashDomain> {
|
||||||
SecretHashDomain::invoke_primitive(&self.0, v.secret(), self.1)
|
SecretHashDomain::invoke_primitive(&self.0, v.secret())
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Gets the key of this [HashDomain].
|
|
||||||
pub fn into_value(self) -> [u8; KEY_LEN] {
|
pub fn into_value(self) -> [u8; KEY_LEN] {
|
||||||
self.0
|
self.0
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl HashDomainNamespace {
|
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> {
|
pub fn mix(&self, v: &[u8]) -> Result<HashDomain> {
|
||||||
let mut new_key: [u8; KEY_LEN] = [0u8; KEY_LEN];
|
Ok(HashDomain(
|
||||||
self.1.keyed_hash_to(&self.0, v).to(&mut new_key)?;
|
hash::hash(&self.0, v).collect::<[u8; KEY_LEN]>()?,
|
||||||
Ok(HashDomain(new_key, self.1.clone()))
|
))
|
||||||
}
|
}
|
||||||
|
|
||||||
/// 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> {
|
pub fn mix_secret<const N: usize>(&self, v: Secret<N>) -> Result<SecretHashDomain> {
|
||||||
SecretHashDomain::invoke_primitive(&self.0, v.secret(), self.1.clone())
|
SecretHashDomain::invoke_primitive(&self.0, v.secret())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl SecretHashDomain {
|
impl SecretHashDomain {
|
||||||
/// Create a new [SecretHashDomain] with the given key `k` and data `d` by calling
|
pub fn invoke_primitive(k: &[u8], d: &[u8]) -> Result<SecretHashDomain> {
|
||||||
/// [hash::hash] with `k` as the `key` and `d` s the `data`, and using the result
|
let mut r = SecretHashDomain(Secret::zero());
|
||||||
/// as the content for the new [SecretHashDomain].
|
hash::hash(k, d).to(r.0.secret_mut())?;
|
||||||
/// Both `k` and `d` have to be exactly [KEY_LEN] bytes in length.
|
|
||||||
/// TODO: docu
|
|
||||||
pub fn invoke_primitive(
|
|
||||||
k: &[u8],
|
|
||||||
d: &[u8],
|
|
||||||
hash_choice: KeyedHash,
|
|
||||||
) -> Result<SecretHashDomain> {
|
|
||||||
let mut new_secret_key = Secret::zero();
|
|
||||||
hash_choice
|
|
||||||
.keyed_hash_to(k.try_into()?, d)
|
|
||||||
.to(new_secret_key.secret_mut())?;
|
|
||||||
let r = SecretHashDomain(new_secret_key, hash_choice);
|
|
||||||
Ok(r)
|
Ok(r)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Creates a new [SecretHashDomain] that is initialized with an all zeros key.
|
pub fn zero() -> Self {
|
||||||
pub fn zero(hash_choice: KeyedHash) -> Self {
|
Self(Secret::zero())
|
||||||
Self(Secret::zero(), hash_choice)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Turns this [SecretHashDomain] into a [SecretHashDomainNamespace].
|
|
||||||
pub fn dup(self) -> SecretHashDomainNamespace {
|
pub fn dup(self) -> SecretHashDomainNamespace {
|
||||||
SecretHashDomainNamespace(self.0, self.1)
|
SecretHashDomainNamespace(self.0)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Creates a new [SecretHashDomain] from a [Secret] `k`.
|
pub fn danger_from_secret(k: Secret<KEY_LEN>) -> Self {
|
||||||
///
|
Self(k)
|
||||||
/// It requires that `k` consist of exactly [KEY_LEN] bytes.
|
|
||||||
pub fn danger_from_secret(k: Secret<KEY_LEN>, hash_choice: KeyedHash) -> Self {
|
|
||||||
Self(k, hash_choice)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// 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> {
|
pub fn mix(self, v: &[u8]) -> Result<SecretHashDomain> {
|
||||||
Self::invoke_primitive(self.0.secret(), v, self.1)
|
Self::invoke_primitive(self.0.secret(), v)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Version of [Self::mix] that accepts an iterator and mixes all values from the iterator into
|
|
||||||
/// this hash domain.
|
|
||||||
///
|
|
||||||
/// # Examples
|
|
||||||
///
|
|
||||||
/// ```rust
|
|
||||||
/// use rosenpass_ciphers::{hash_domain::HashDomain, KeyedHash};
|
|
||||||
///
|
|
||||||
/// rosenpass_secret_memory::secret_policy_use_only_malloc_secrets();
|
|
||||||
///
|
|
||||||
/// let hasher = HashDomain::zero(KeyedHash::keyed_shake256());
|
|
||||||
/// assert_eq!(
|
|
||||||
/// hasher
|
|
||||||
/// .clone()
|
|
||||||
/// .turn_secret()
|
|
||||||
/// .mix(b"Hello")?
|
|
||||||
/// .mix(b"World")?
|
|
||||||
/// .into_secret()
|
|
||||||
/// .secret(),
|
|
||||||
/// hasher
|
|
||||||
/// .clone()
|
|
||||||
/// .turn_secret()
|
|
||||||
/// .mix_many([b"Hello", b"World"])?
|
|
||||||
/// .into_secret()
|
|
||||||
/// .secret(),
|
|
||||||
/// );
|
|
||||||
|
|
||||||
/// Ok::<(), anyhow::Error>(())
|
|
||||||
/// ```
|
|
||||||
pub fn mix_many<I, T>(mut self, it: I) -> Result<Self>
|
|
||||||
where
|
|
||||||
I: IntoIterator<Item = T>,
|
|
||||||
T: AsRef<[u8]>,
|
|
||||||
{
|
|
||||||
for e in it {
|
|
||||||
self = self.mix(e.as_ref())?;
|
|
||||||
}
|
|
||||||
Ok(self)
|
|
||||||
}
|
|
||||||
|
|
||||||
/// 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> {
|
pub fn mix_secret<const N: usize>(self, v: Secret<N>) -> Result<SecretHashDomain> {
|
||||||
Self::invoke_primitive(self.0.secret(), v.secret(), self.1)
|
Self::invoke_primitive(self.0.secret(), v.secret())
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Get the secret key data from this [SecretHashDomain].
|
|
||||||
pub fn into_secret(self) -> Secret<KEY_LEN> {
|
pub fn into_secret(self) -> Secret<KEY_LEN> {
|
||||||
self.0
|
self.0
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn into_secret_slice(mut self, v: &[u8], dst: &[u8]) -> Result<()> {
|
||||||
|
hash::hash(v, dst).to(self.0.secret_mut())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl SecretHashDomainNamespace {
|
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> {
|
pub fn mix(&self, v: &[u8]) -> Result<SecretHashDomain> {
|
||||||
SecretHashDomain::invoke_primitive(self.0.secret(), v, self.1.clone())
|
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> {
|
pub fn mix_secret<const N: usize>(&self, v: Secret<N>) -> Result<SecretHashDomain> {
|
||||||
SecretHashDomain::invoke_primitive(self.0.secret(), v.secret(), self.1.clone())
|
SecretHashDomain::invoke_primitive(self.0.secret(), v.secret())
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: This entire API is not very nice; we need this for biscuits, but
|
// TODO: This entire API is not very nice; we need this for biscuits, but
|
||||||
// it might be better to extract a special "biscuit"
|
// it might be better to extract a special "biscuit"
|
||||||
// labeled subkey and reinitialize the chain with this
|
// 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> {
|
pub fn danger_into_secret(self) -> Secret<KEY_LEN> {
|
||||||
self.0
|
self.0
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn keyed_hash(&self) -> &KeyedHash {
|
|
||||||
&self.1
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,46 +1,32 @@
|
|||||||
use rosenpass_cipher_traits::primitives::Aead as AeadTrait;
|
|
||||||
use static_assertions::const_assert;
|
use static_assertions::const_assert;
|
||||||
|
|
||||||
pub mod subtle;
|
pub mod subtle;
|
||||||
|
|
||||||
/// All keyed primitives in this crate use 32 byte keys
|
|
||||||
pub const KEY_LEN: usize = 32;
|
pub const KEY_LEN: usize = 32;
|
||||||
const_assert!(KEY_LEN == Aead::KEY_LEN);
|
const_assert!(KEY_LEN == aead::KEY_LEN);
|
||||||
const_assert!(KEY_LEN == XAead::KEY_LEN);
|
const_assert!(KEY_LEN == xaead::KEY_LEN);
|
||||||
const_assert!(KEY_LEN == hash_domain::KEY_LEN);
|
const_assert!(KEY_LEN == hash_domain::KEY_LEN);
|
||||||
|
|
||||||
/// Keyed hashing
|
/// Authenticated encryption with associated data
|
||||||
///
|
pub mod aead {
|
||||||
/// This should only be used for implementation details; anything with relevance
|
#[cfg(not(feature = "experiment_libcrux"))]
|
||||||
/// to the cryptographic protocol should use the facilities in [hash_domain], (though
|
pub use crate::subtle::chacha20poly1305_ietf::{decrypt, encrypt, KEY_LEN, NONCE_LEN, TAG_LEN};
|
||||||
/// hash domain uses this module internally)
|
#[cfg(feature = "experiment_libcrux")]
|
||||||
pub use crate::subtle::keyed_hash::KeyedHash;
|
pub use crate::subtle::chacha20poly1305_ietf_libcrux::{
|
||||||
|
decrypt, encrypt, KEY_LEN, NONCE_LEN, TAG_LEN,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
/// Authenticated encryption with associated data (AEAD)
|
/// Authenticated encryption with associated data with a constant nonce
|
||||||
/// Chacha20poly1305 is used.
|
pub mod xaead {
|
||||||
#[cfg(feature = "experiment_libcrux_chachapoly")]
|
pub use crate::subtle::xchacha20poly1305_ietf::{
|
||||||
pub use subtle::libcrux::chacha20poly1305_ietf::ChaCha20Poly1305 as Aead;
|
decrypt, encrypt, KEY_LEN, NONCE_LEN, TAG_LEN,
|
||||||
|
};
|
||||||
/// Authenticated encryption with associated data (AEAD)
|
}
|
||||||
/// Chacha20poly1305 is used.
|
|
||||||
#[cfg(not(feature = "experiment_libcrux_chachapoly"))]
|
|
||||||
pub use crate::subtle::rust_crypto::chacha20poly1305_ietf::ChaCha20Poly1305 as Aead;
|
|
||||||
|
|
||||||
/// Authenticated encryption with associated data with a extended-length nonce (XAEAD)
|
|
||||||
/// XChacha20poly1305 is used.
|
|
||||||
pub use crate::subtle::rust_crypto::xchacha20poly1305_ietf::XChaCha20Poly1305 as XAead;
|
|
||||||
|
|
||||||
/// Use Classic-McEcliece-460986 as the Static KEM.
|
|
||||||
///
|
|
||||||
/// See [rosenpass_oqs::ClassicMceliece460896] for more details.
|
|
||||||
pub use rosenpass_oqs::ClassicMceliece460896 as StaticKem;
|
|
||||||
|
|
||||||
/// Use Kyber-512 as the Static KEM
|
|
||||||
///
|
|
||||||
/// See [rosenpass_oqs::Kyber512] for more details.
|
|
||||||
#[cfg(not(feature = "experiment_libcrux_kyber"))]
|
|
||||||
pub use rosenpass_oqs::Kyber512 as EphemeralKem;
|
|
||||||
#[cfg(feature = "experiment_libcrux_kyber")]
|
|
||||||
pub use subtle::libcrux::kyber512::Kyber512 as EphemeralKem;
|
|
||||||
|
|
||||||
pub mod hash_domain;
|
pub mod hash_domain;
|
||||||
|
|
||||||
|
pub mod kem {
|
||||||
|
pub use rosenpass_oqs::ClassicMceliece460896 as StaticKem;
|
||||||
|
pub use rosenpass_oqs::Kyber512 as EphemeralKem;
|
||||||
|
}
|
||||||
|
|||||||
42
ciphers/src/subtle/blake2b.rs
Normal file
@@ -0,0 +1,42 @@
|
|||||||
|
use zeroize::Zeroizing;
|
||||||
|
|
||||||
|
use blake2::digest::crypto_common::generic_array::GenericArray;
|
||||||
|
use blake2::digest::crypto_common::typenum::U32;
|
||||||
|
use blake2::digest::crypto_common::KeySizeUser;
|
||||||
|
use blake2::digest::{FixedOutput, Mac, OutputSizeUser};
|
||||||
|
use blake2::Blake2bMac;
|
||||||
|
|
||||||
|
use rosenpass_to::{ops::copy_slice, with_destination, To};
|
||||||
|
use rosenpass_util::typenum2const;
|
||||||
|
|
||||||
|
type Impl = Blake2bMac<U32>;
|
||||||
|
|
||||||
|
type KeyLen = <Impl as KeySizeUser>::KeySize;
|
||||||
|
type OutLen = <Impl as OutputSizeUser>::OutputSize;
|
||||||
|
|
||||||
|
const KEY_LEN: usize = typenum2const! { KeyLen };
|
||||||
|
const OUT_LEN: usize = typenum2const! { OutLen };
|
||||||
|
|
||||||
|
pub const KEY_MIN: usize = KEY_LEN;
|
||||||
|
pub const KEY_MAX: usize = KEY_LEN;
|
||||||
|
pub const OUT_MIN: usize = OUT_LEN;
|
||||||
|
pub const OUT_MAX: usize = OUT_LEN;
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
pub fn hash<'a>(key: &'a [u8], data: &'a [u8]) -> impl To<[u8], anyhow::Result<()>> + 'a {
|
||||||
|
with_destination(|out: &mut [u8]| {
|
||||||
|
let mut h = Impl::new_from_slice(key)?;
|
||||||
|
h.update(data);
|
||||||
|
|
||||||
|
// Jesus christ, blake2 crate, your usage of GenericArray might be nice and fancy
|
||||||
|
// but it introduces a ton of complexity. This cost me half an hour just to figure
|
||||||
|
// out the right way to use the imports while allowing for zeroization.
|
||||||
|
// An API based on slices might actually be simpler.
|
||||||
|
let mut tmp = Zeroizing::new([0u8; OUT_LEN]);
|
||||||
|
let tmp = GenericArray::from_mut_slice(tmp.as_mut());
|
||||||
|
h.finalize_into(tmp);
|
||||||
|
copy_slice(tmp.as_ref()).to(out);
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
})
|
||||||
|
}
|
||||||
43
ciphers/src/subtle/chacha20poly1305_ietf.rs
Normal file
@@ -0,0 +1,43 @@
|
|||||||
|
use rosenpass_to::ops::copy_slice;
|
||||||
|
use rosenpass_to::To;
|
||||||
|
use rosenpass_util::typenum2const;
|
||||||
|
|
||||||
|
use chacha20poly1305::aead::generic_array::GenericArray;
|
||||||
|
use chacha20poly1305::ChaCha20Poly1305 as AeadImpl;
|
||||||
|
use chacha20poly1305::{AeadCore, AeadInPlace, KeyInit, KeySizeUser};
|
||||||
|
|
||||||
|
pub const KEY_LEN: usize = typenum2const! { <AeadImpl as KeySizeUser>::KeySize };
|
||||||
|
pub const TAG_LEN: usize = typenum2const! { <AeadImpl as AeadCore>::TagSize };
|
||||||
|
pub const NONCE_LEN: usize = typenum2const! { <AeadImpl as AeadCore>::NonceSize };
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
pub fn encrypt(
|
||||||
|
ciphertext: &mut [u8],
|
||||||
|
key: &[u8],
|
||||||
|
nonce: &[u8],
|
||||||
|
ad: &[u8],
|
||||||
|
plaintext: &[u8],
|
||||||
|
) -> anyhow::Result<()> {
|
||||||
|
let nonce = GenericArray::from_slice(nonce);
|
||||||
|
let (ct, mac) = ciphertext.split_at_mut(ciphertext.len() - TAG_LEN);
|
||||||
|
copy_slice(plaintext).to(ct);
|
||||||
|
let mac_value = AeadImpl::new_from_slice(key)?.encrypt_in_place_detached(nonce, ad, ct)?;
|
||||||
|
copy_slice(&mac_value[..]).to(mac);
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
pub fn decrypt(
|
||||||
|
plaintext: &mut [u8],
|
||||||
|
key: &[u8],
|
||||||
|
nonce: &[u8],
|
||||||
|
ad: &[u8],
|
||||||
|
ciphertext: &[u8],
|
||||||
|
) -> anyhow::Result<()> {
|
||||||
|
let nonce = GenericArray::from_slice(nonce);
|
||||||
|
let (ct, mac) = ciphertext.split_at(ciphertext.len() - TAG_LEN);
|
||||||
|
let tag = GenericArray::from_slice(mac);
|
||||||
|
copy_slice(ct).to(plaintext);
|
||||||
|
AeadImpl::new_from_slice(key)?.decrypt_in_place_detached(nonce, ad, plaintext, tag)?;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
60
ciphers/src/subtle/chacha20poly1305_ietf_libcrux.rs
Normal file
@@ -0,0 +1,60 @@
|
|||||||
|
use rosenpass_to::ops::copy_slice;
|
||||||
|
use rosenpass_to::To;
|
||||||
|
|
||||||
|
use zeroize::Zeroize;
|
||||||
|
|
||||||
|
pub const KEY_LEN: usize = 32; // Grrrr! Libcrux, please provide me these constants.
|
||||||
|
pub const TAG_LEN: usize = 16;
|
||||||
|
pub const NONCE_LEN: usize = 12;
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
pub fn encrypt(
|
||||||
|
ciphertext: &mut [u8],
|
||||||
|
key: &[u8],
|
||||||
|
nonce: &[u8],
|
||||||
|
ad: &[u8],
|
||||||
|
plaintext: &[u8],
|
||||||
|
) -> anyhow::Result<()> {
|
||||||
|
let (ciphertext, mac) = ciphertext.split_at_mut(ciphertext.len() - TAG_LEN);
|
||||||
|
|
||||||
|
use libcrux::aead as C;
|
||||||
|
let crux_key = C::Key::Chacha20Poly1305(C::Chacha20Key(key.try_into().unwrap()));
|
||||||
|
let crux_iv = C::Iv(nonce.try_into().unwrap());
|
||||||
|
|
||||||
|
copy_slice(plaintext).to(ciphertext);
|
||||||
|
let crux_tag = libcrux::aead::encrypt(&crux_key, ciphertext, crux_iv, ad).unwrap();
|
||||||
|
copy_slice(crux_tag.as_ref()).to(mac);
|
||||||
|
|
||||||
|
match crux_key {
|
||||||
|
C::Key::Chacha20Poly1305(mut k) => k.0.zeroize(),
|
||||||
|
_ => panic!(),
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
pub fn decrypt(
|
||||||
|
plaintext: &mut [u8],
|
||||||
|
key: &[u8],
|
||||||
|
nonce: &[u8],
|
||||||
|
ad: &[u8],
|
||||||
|
ciphertext: &[u8],
|
||||||
|
) -> anyhow::Result<()> {
|
||||||
|
let (ciphertext, mac) = ciphertext.split_at(ciphertext.len() - TAG_LEN);
|
||||||
|
|
||||||
|
use libcrux::aead as C;
|
||||||
|
let crux_key = C::Key::Chacha20Poly1305(C::Chacha20Key(key.try_into().unwrap()));
|
||||||
|
let crux_iv = C::Iv(nonce.try_into().unwrap());
|
||||||
|
let crux_tag = C::Tag::from_slice(mac).unwrap();
|
||||||
|
|
||||||
|
copy_slice(ciphertext).to(plaintext);
|
||||||
|
libcrux::aead::decrypt(&crux_key, plaintext, crux_iv, ad, &crux_tag).unwrap();
|
||||||
|
|
||||||
|
match crux_key {
|
||||||
|
C::Key::Chacha20Poly1305(mut k) => k.0.zeroize(),
|
||||||
|
_ => panic!(),
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
@@ -1,79 +0,0 @@
|
|||||||
use rosenpass_cipher_traits::{
|
|
||||||
algorithms::KeyedHashIncorrectHmacBlake2b,
|
|
||||||
primitives::{InferKeyedHash, KeyedHash, KeyedHashTo},
|
|
||||||
};
|
|
||||||
use rosenpass_constant_time::xor;
|
|
||||||
use rosenpass_to::{ops::copy_slice, To};
|
|
||||||
use zeroize::Zeroizing;
|
|
||||||
|
|
||||||
#[cfg(not(feature = "experiment_libcrux_blake2"))]
|
|
||||||
use crate::subtle::rust_crypto::blake2b::Blake2b;
|
|
||||||
#[cfg(not(feature = "experiment_libcrux_blake2"))]
|
|
||||||
use anyhow::Error;
|
|
||||||
|
|
||||||
#[cfg(feature = "experiment_libcrux_blake2")]
|
|
||||||
use crate::subtle::libcrux::blake2b::{Blake2b, Error};
|
|
||||||
|
|
||||||
/// The key length, 32 bytes or 256 bits.
|
|
||||||
pub const KEY_LEN: usize = 32;
|
|
||||||
|
|
||||||
/// The hash length, 32 bytes or 256 bits.
|
|
||||||
pub const HASH_LEN: usize = 32;
|
|
||||||
|
|
||||||
/// 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::custom::incorrect_hmac_blake2b::IncorrectHmacBlake2bCore;
|
|
||||||
/// use rosenpass_cipher_traits::primitives::KeyedHashTo;
|
|
||||||
/// 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!(IncorrectHmacBlake2bCore::keyed_hash_to(&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);
|
|
||||||
///```
|
|
||||||
///
|
|
||||||
#[derive(Clone, Debug, PartialEq, Eq)]
|
|
||||||
pub struct IncorrectHmacBlake2bCore;
|
|
||||||
|
|
||||||
impl KeyedHash<KEY_LEN, HASH_LEN> for IncorrectHmacBlake2bCore {
|
|
||||||
type Error = Error;
|
|
||||||
|
|
||||||
fn keyed_hash(
|
|
||||||
key: &[u8; KEY_LEN],
|
|
||||||
data: &[u8],
|
|
||||||
out: &mut [u8; HASH_LEN],
|
|
||||||
) -> Result<(), Self::Error> {
|
|
||||||
const IPAD: [u8; KEY_LEN] = [0x36u8; KEY_LEN];
|
|
||||||
const OPAD: [u8; KEY_LEN] = [0x5Cu8; 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::keyed_hash_to(&tmp_key, data).to(&mut outer_data)?;
|
|
||||||
|
|
||||||
copy_slice(key).to(tmp_key.as_mut());
|
|
||||||
xor(&OPAD).to(tmp_key.as_mut());
|
|
||||||
Blake2b::keyed_hash_to(&tmp_key, outer_data.as_ref()).to(out)?;
|
|
||||||
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub type IncorrectHmacBlake2b = InferKeyedHash<IncorrectHmacBlake2bCore, KEY_LEN, HASH_LEN>;
|
|
||||||
|
|
||||||
impl KeyedHashIncorrectHmacBlake2b for IncorrectHmacBlake2bCore {}
|
|
||||||
@@ -1,3 +0,0 @@
|
|||||||
//! Own implementations of custom algorithms
|
|
||||||
|
|
||||||
pub mod incorrect_hmac_blake2b;
|
|
||||||
46
ciphers/src/subtle/incorrect_hmac_blake2b.rs
Normal file
@@ -0,0 +1,46 @@
|
|||||||
|
use anyhow::ensure;
|
||||||
|
use zeroize::Zeroizing;
|
||||||
|
|
||||||
|
use rosenpass_constant_time::xor;
|
||||||
|
use rosenpass_to::{ops::copy_slice, with_destination, To};
|
||||||
|
|
||||||
|
use crate::subtle::blake2b;
|
||||||
|
|
||||||
|
pub const KEY_LEN: usize = 32;
|
||||||
|
pub const KEY_MIN: usize = KEY_LEN;
|
||||||
|
pub const KEY_MAX: usize = KEY_LEN;
|
||||||
|
pub const OUT_MIN: usize = blake2b::OUT_MIN;
|
||||||
|
pub const OUT_MAX: usize = blake2b::OUT_MAX;
|
||||||
|
|
||||||
|
/// This is a woefully incorrect implementation of hmac_blake2b.
|
||||||
|
/// See <https://github.com/rosenpass/rosenpass/issues/68#issuecomment-1563612222>
|
||||||
|
///
|
||||||
|
/// It accepts 32 byte keys, exclusively.
|
||||||
|
///
|
||||||
|
/// This will be replaced, likely by Kekkac at some point soon.
|
||||||
|
/// <https://github.com/rosenpass/rosenpass/pull/145>
|
||||||
|
#[inline]
|
||||||
|
pub fn hash<'a>(key: &'a [u8], data: &'a [u8]) -> impl To<[u8], anyhow::Result<()>> + 'a {
|
||||||
|
const IPAD: [u8; KEY_LEN] = [0x36u8; KEY_LEN];
|
||||||
|
const OPAD: [u8; KEY_LEN] = [0x5Cu8; KEY_LEN];
|
||||||
|
|
||||||
|
with_destination(|out: &mut [u8]| {
|
||||||
|
// Not bothering with padding; the implementation
|
||||||
|
// uses appropriately sized keys.
|
||||||
|
ensure!(key.len() == KEY_LEN);
|
||||||
|
|
||||||
|
type Key = Zeroizing<[u8; KEY_LEN]>;
|
||||||
|
let mut tmp_key = Key::default();
|
||||||
|
|
||||||
|
copy_slice(key).to(tmp_key.as_mut());
|
||||||
|
xor(&IPAD).to(tmp_key.as_mut());
|
||||||
|
let mut outer_data = Key::default();
|
||||||
|
blake2b::hash(tmp_key.as_ref(), data).to(outer_data.as_mut())?;
|
||||||
|
|
||||||
|
copy_slice(key).to(tmp_key.as_mut());
|
||||||
|
xor(&OPAD).to(tmp_key.as_mut());
|
||||||
|
blake2b::hash(tmp_key.as_ref(), outer_data.as_ref()).to(out)?;
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
})
|
||||||
|
}
|
||||||
@@ -1,65 +0,0 @@
|
|||||||
//! This module provides types that enabling choosing the keyed hash building block to be used at
|
|
||||||
//! runtime (using enums) instead of at compile time (using generics).
|
|
||||||
|
|
||||||
use anyhow::Result;
|
|
||||||
use rosenpass_cipher_traits::primitives::KeyedHashInstance;
|
|
||||||
use std::fmt::Display;
|
|
||||||
|
|
||||||
use crate::subtle::{
|
|
||||||
custom::incorrect_hmac_blake2b::IncorrectHmacBlake2b, rust_crypto::keyed_shake256::SHAKE256_32,
|
|
||||||
};
|
|
||||||
|
|
||||||
/// Length of symmetric key throughout Rosenpass.
|
|
||||||
pub const KEY_LEN: usize = 32;
|
|
||||||
|
|
||||||
/// The hash is used as a symmetric key and should have the same length.
|
|
||||||
pub const HASH_LEN: usize = KEY_LEN;
|
|
||||||
|
|
||||||
/// Provides a way to pick which keyed hash to use at runtime.
|
|
||||||
/// Implements [`KeyedHashInstance`] to allow hashing using the respective algorithm.
|
|
||||||
#[derive(Debug, Eq, PartialEq, Clone)]
|
|
||||||
pub enum KeyedHash {
|
|
||||||
/// A hasher backed by [`SHAKE256_32`].
|
|
||||||
KeyedShake256(SHAKE256_32),
|
|
||||||
/// A hasher backed by [`IncorrectHmacBlake2b`].
|
|
||||||
IncorrectHmacBlake2b(IncorrectHmacBlake2b),
|
|
||||||
}
|
|
||||||
|
|
||||||
impl KeyedHash {
|
|
||||||
/// Creates an [`KeyedHash`] backed by SHAKE256.
|
|
||||||
pub fn keyed_shake256() -> Self {
|
|
||||||
Self::KeyedShake256(Default::default())
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Creates an [`KeyedHash`] backed by Blake2B.
|
|
||||||
pub fn incorrect_hmac_blake2b() -> Self {
|
|
||||||
Self::IncorrectHmacBlake2b(Default::default())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl KeyedHashInstance<KEY_LEN, HASH_LEN> for KeyedHash {
|
|
||||||
type Error = anyhow::Error;
|
|
||||||
|
|
||||||
fn keyed_hash(
|
|
||||||
&self,
|
|
||||||
key: &[u8; KEY_LEN],
|
|
||||||
data: &[u8],
|
|
||||||
out: &mut [u8; HASH_LEN],
|
|
||||||
) -> Result<(), Self::Error> {
|
|
||||||
match self {
|
|
||||||
Self::KeyedShake256(h) => h.keyed_hash(key, data, out)?,
|
|
||||||
Self::IncorrectHmacBlake2b(h) => h.keyed_hash(key, data, out)?,
|
|
||||||
};
|
|
||||||
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Display for KeyedHash {
|
|
||||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
|
||||||
match self {
|
|
||||||
Self::KeyedShake256(_) => write!(f, "KeyedShake256_32"),
|
|
||||||
Self::IncorrectHmacBlake2b(_) => write!(f, "IncorrectHmacBlake2b"),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,88 +0,0 @@
|
|||||||
//! Implementation of the [`KeyedHashBlake2b`] trait based on the [`libcrux_blake2`] crate.
|
|
||||||
|
|
||||||
use libcrux_blake2::Blake2bBuilder;
|
|
||||||
|
|
||||||
use rosenpass_cipher_traits::algorithms::KeyedHashBlake2b;
|
|
||||||
use rosenpass_cipher_traits::primitives::KeyedHash;
|
|
||||||
|
|
||||||
pub use rosenpass_cipher_traits::algorithms::keyed_hash_blake2b::HASH_LEN;
|
|
||||||
pub use rosenpass_cipher_traits::algorithms::keyed_hash_blake2b::KEY_LEN;
|
|
||||||
|
|
||||||
/// Describles which error occurred
|
|
||||||
#[derive(Debug, thiserror::Error)]
|
|
||||||
pub enum Error {
|
|
||||||
/// An unexpected internal error occurred. Should never be returned and points to a bug in the
|
|
||||||
/// implementation.
|
|
||||||
#[error("internal error")]
|
|
||||||
InternalError,
|
|
||||||
|
|
||||||
/// Indicates that the provided data was too long.
|
|
||||||
#[error("data is too long")]
|
|
||||||
DataTooLong,
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Hasher for the given `data` with the Blake2b hash function.
|
|
||||||
pub struct Blake2b;
|
|
||||||
|
|
||||||
impl KeyedHash<KEY_LEN, HASH_LEN> for Blake2b {
|
|
||||||
type Error = Error;
|
|
||||||
|
|
||||||
fn keyed_hash(
|
|
||||||
key: &[u8; KEY_LEN],
|
|
||||||
data: &[u8],
|
|
||||||
out: &mut [u8; HASH_LEN],
|
|
||||||
) -> Result<(), Self::Error> {
|
|
||||||
let mut h = Blake2bBuilder::new_keyed_const(key)
|
|
||||||
// this may fail if the key length is invalid, but 32 is fine
|
|
||||||
.map_err(|_| Error::InternalError)?
|
|
||||||
.build_const_digest_len()
|
|
||||||
.map_err(|_|
|
|
||||||
// this can only fail if the output length is invalid, but 32 is fine.
|
|
||||||
Error::InternalError)?;
|
|
||||||
|
|
||||||
h.update(data).map_err(|_| Error::DataTooLong)?;
|
|
||||||
h.finalize(out);
|
|
||||||
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl KeyedHashBlake2b for Blake2b {}
|
|
||||||
|
|
||||||
#[cfg(test)]
|
|
||||||
mod equivalence_tests {
|
|
||||||
use super::*;
|
|
||||||
use rand::RngCore;
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn fuzz_equivalence_libcrux_old_new() {
|
|
||||||
let datas: [&[u8]; 3] = [
|
|
||||||
b"".as_slice(),
|
|
||||||
b"test".as_slice(),
|
|
||||||
b"abcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcd",
|
|
||||||
];
|
|
||||||
|
|
||||||
let mut key = [0; KEY_LEN];
|
|
||||||
let mut rng = rand::thread_rng();
|
|
||||||
|
|
||||||
let mut hash_left = [0; 32];
|
|
||||||
let mut hash_right = [0; 32];
|
|
||||||
|
|
||||||
for data in datas {
|
|
||||||
for _ in 0..1000 {
|
|
||||||
rng.fill_bytes(&mut key);
|
|
||||||
|
|
||||||
crate::subtle::rust_crypto::blake2b::Blake2b::keyed_hash(
|
|
||||||
&key,
|
|
||||||
data,
|
|
||||||
&mut hash_left,
|
|
||||||
)
|
|
||||||
.unwrap();
|
|
||||||
crate::subtle::libcrux::blake2b::Blake2b::keyed_hash(&key, data, &mut hash_right)
|
|
||||||
.unwrap();
|
|
||||||
|
|
||||||
assert_eq!(hash_left, hash_right);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,274 +0,0 @@
|
|||||||
//! Implementation of the [`AeadChaCha20Poly1305`] trait based on the [`libcrux_chacha20poly1305`] crate.
|
|
||||||
|
|
||||||
use rosenpass_cipher_traits::algorithms::AeadChaCha20Poly1305;
|
|
||||||
use rosenpass_cipher_traits::primitives::{Aead, AeadError};
|
|
||||||
|
|
||||||
pub use rosenpass_cipher_traits::algorithms::aead_chacha20poly1305::{KEY_LEN, NONCE_LEN, TAG_LEN};
|
|
||||||
|
|
||||||
/// An implementation of the ChaCha20Poly1305 AEAD based on libcrux
|
|
||||||
pub struct ChaCha20Poly1305;
|
|
||||||
|
|
||||||
impl Aead<KEY_LEN, NONCE_LEN, TAG_LEN> for ChaCha20Poly1305 {
|
|
||||||
fn encrypt(
|
|
||||||
&self,
|
|
||||||
ciphertext: &mut [u8],
|
|
||||||
key: &[u8; KEY_LEN],
|
|
||||||
nonce: &[u8; NONCE_LEN],
|
|
||||||
ad: &[u8],
|
|
||||||
plaintext: &[u8],
|
|
||||||
) -> Result<(), AeadError> {
|
|
||||||
let (ctxt, tag) = libcrux_chacha20poly1305::encrypt(key, plaintext, ciphertext, ad, nonce)
|
|
||||||
.map_err(|_| AeadError::InternalError)?;
|
|
||||||
|
|
||||||
// return an error of the destination buffer is longer than expected
|
|
||||||
// because the caller wouldn't know where the end is
|
|
||||||
if ctxt.len() + tag.len() != ciphertext.len() {
|
|
||||||
return Err(AeadError::InternalError);
|
|
||||||
}
|
|
||||||
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
fn decrypt(
|
|
||||||
&self,
|
|
||||||
plaintext: &mut [u8],
|
|
||||||
key: &[u8; KEY_LEN],
|
|
||||||
nonce: &[u8; NONCE_LEN],
|
|
||||||
ad: &[u8],
|
|
||||||
ciphertext: &[u8],
|
|
||||||
) -> Result<(), AeadError> {
|
|
||||||
let ptxt = libcrux_chacha20poly1305::decrypt(key, plaintext, ciphertext, ad, nonce)
|
|
||||||
.map_err(|_| AeadError::DecryptError)?;
|
|
||||||
|
|
||||||
// return an error of the destination buffer is longer than expected
|
|
||||||
// because the caller wouldn't know where the end is
|
|
||||||
if ptxt.len() != plaintext.len() {
|
|
||||||
return Err(AeadError::DecryptError);
|
|
||||||
}
|
|
||||||
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl AeadChaCha20Poly1305 for ChaCha20Poly1305 {}
|
|
||||||
|
|
||||||
/// The idea of these tests is to check that the above implemenatation behaves, by and large, the
|
|
||||||
/// same as the one from the old libcrux and the one from RustCrypto. You can consider them janky,
|
|
||||||
/// self-rolled property-based tests.
|
|
||||||
#[cfg(test)]
|
|
||||||
mod equivalence_tests {
|
|
||||||
use super::*;
|
|
||||||
use rand::RngCore;
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn proptest_equivalence_libcrux_rustcrypto() {
|
|
||||||
use crate::subtle::rust_crypto::chacha20poly1305_ietf::ChaCha20Poly1305 as RustCryptoChaCha20Poly1305;
|
|
||||||
let ptxts: [&[u8]; 3] = [
|
|
||||||
b"".as_slice(),
|
|
||||||
b"test".as_slice(),
|
|
||||||
b"abcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcd",
|
|
||||||
];
|
|
||||||
let mut key = [0; KEY_LEN];
|
|
||||||
let mut rng = rand::thread_rng();
|
|
||||||
|
|
||||||
let mut ctxt_left = [0; 64 + TAG_LEN];
|
|
||||||
let mut ctxt_right = [0; 64 + TAG_LEN];
|
|
||||||
|
|
||||||
let mut ptxt_left = [0; 64];
|
|
||||||
let mut ptxt_right = [0; 64];
|
|
||||||
|
|
||||||
let nonce = [0; NONCE_LEN];
|
|
||||||
let ad = b"";
|
|
||||||
|
|
||||||
for ptxt in ptxts {
|
|
||||||
for _ in 0..1000 {
|
|
||||||
rng.fill_bytes(&mut key);
|
|
||||||
let ctxt_left = &mut ctxt_left[..ptxt.len() + TAG_LEN];
|
|
||||||
let ctxt_right = &mut ctxt_right[..ptxt.len() + TAG_LEN];
|
|
||||||
|
|
||||||
let ptxt_left = &mut ptxt_left[..ptxt.len()];
|
|
||||||
let ptxt_right = &mut ptxt_right[..ptxt.len()];
|
|
||||||
|
|
||||||
RustCryptoChaCha20Poly1305
|
|
||||||
.encrypt(ctxt_left, &key, &nonce, ad, ptxt)
|
|
||||||
.unwrap();
|
|
||||||
ChaCha20Poly1305
|
|
||||||
.encrypt(ctxt_right, &key, &nonce, ad, ptxt)
|
|
||||||
.unwrap();
|
|
||||||
|
|
||||||
assert_eq!(ctxt_left, ctxt_right);
|
|
||||||
|
|
||||||
RustCryptoChaCha20Poly1305
|
|
||||||
.decrypt(ptxt_left, &key, &nonce, ad, ctxt_left)
|
|
||||||
.unwrap();
|
|
||||||
ChaCha20Poly1305
|
|
||||||
.decrypt(ptxt_right, &key, &nonce, ad, ctxt_right)
|
|
||||||
.unwrap();
|
|
||||||
|
|
||||||
assert_eq!(ptxt_left, ptxt);
|
|
||||||
assert_eq!(ptxt_right, ptxt);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
#[cfg(feature = "experiment_libcrux_chachapoly_test")]
|
|
||||||
fn proptest_equivalence_libcrux_old_new() {
|
|
||||||
let ptxts: [&[u8]; 3] = [
|
|
||||||
b"".as_slice(),
|
|
||||||
b"test".as_slice(),
|
|
||||||
b"abcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcd",
|
|
||||||
];
|
|
||||||
let mut key = [0; KEY_LEN];
|
|
||||||
let mut rng = rand::thread_rng();
|
|
||||||
|
|
||||||
let mut ctxt_left = [0; 64 + TAG_LEN];
|
|
||||||
let mut ctxt_right = [0; 64 + TAG_LEN];
|
|
||||||
|
|
||||||
let mut ptxt_left = [0; 64];
|
|
||||||
let mut ptxt_right = [0; 64];
|
|
||||||
|
|
||||||
let nonce = [0; NONCE_LEN];
|
|
||||||
let ad = b"";
|
|
||||||
|
|
||||||
for ptxt in ptxts {
|
|
||||||
for _ in 0..1000 {
|
|
||||||
rng.fill_bytes(&mut key);
|
|
||||||
let ctxt_left = &mut ctxt_left[..ptxt.len() + TAG_LEN];
|
|
||||||
let ctxt_right = &mut ctxt_right[..ptxt.len() + TAG_LEN];
|
|
||||||
|
|
||||||
let ptxt_left = &mut ptxt_left[..ptxt.len()];
|
|
||||||
let ptxt_right = &mut ptxt_right[..ptxt.len()];
|
|
||||||
|
|
||||||
encrypt(ctxt_left, &key, &nonce, ad, ptxt).unwrap();
|
|
||||||
ChaCha20Poly1305
|
|
||||||
.encrypt(ctxt_right, &key, &nonce, ad, ptxt)
|
|
||||||
.unwrap();
|
|
||||||
|
|
||||||
assert_eq!(ctxt_left, ctxt_right);
|
|
||||||
|
|
||||||
decrypt(ptxt_left, &key, &nonce, ad, ctxt_left).unwrap();
|
|
||||||
ChaCha20Poly1305
|
|
||||||
.decrypt(ptxt_right, &key, &nonce, ad, ctxt_right)
|
|
||||||
.unwrap();
|
|
||||||
|
|
||||||
assert_eq!(ptxt_left, ptxt);
|
|
||||||
assert_eq!(ptxt_right, ptxt);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// The old libcrux functions:
|
|
||||||
|
|
||||||
// The functions below are from the old libcrux backend. I am keeping them around so we can
|
|
||||||
// check if they behave the same.
|
|
||||||
use rosenpass_to::ops::copy_slice;
|
|
||||||
use rosenpass_to::To;
|
|
||||||
use zeroize::Zeroize;
|
|
||||||
|
|
||||||
/// 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,133 +0,0 @@
|
|||||||
//! Implementation of the [`KemKyber512`] trait based on the [`libcrux_ml_kem`] crate.
|
|
||||||
|
|
||||||
use libcrux_ml_kem::kyber512;
|
|
||||||
use rand::RngCore;
|
|
||||||
|
|
||||||
use rosenpass_cipher_traits::algorithms::KemKyber512;
|
|
||||||
use rosenpass_cipher_traits::primitives::{Kem, KemError};
|
|
||||||
|
|
||||||
pub use rosenpass_cipher_traits::algorithms::kem_kyber512::{CT_LEN, PK_LEN, SHK_LEN, SK_LEN};
|
|
||||||
|
|
||||||
/// An implementation of the Kyber512 KEM based on libcrux
|
|
||||||
pub struct Kyber512;
|
|
||||||
|
|
||||||
impl Kem<SK_LEN, PK_LEN, CT_LEN, SHK_LEN> for Kyber512 {
|
|
||||||
fn keygen(&self, sk: &mut [u8; SK_LEN], pk: &mut [u8; PK_LEN]) -> Result<(), KemError> {
|
|
||||||
let mut randomness = [0u8; libcrux_ml_kem::KEY_GENERATION_SEED_SIZE];
|
|
||||||
rand::thread_rng().fill_bytes(&mut randomness);
|
|
||||||
|
|
||||||
let key_pair = kyber512::generate_key_pair(randomness);
|
|
||||||
|
|
||||||
let new_sk: &[u8; SK_LEN] = key_pair.sk();
|
|
||||||
let new_pk: &[u8; PK_LEN] = key_pair.pk();
|
|
||||||
|
|
||||||
sk.clone_from_slice(new_sk);
|
|
||||||
pk.clone_from_slice(new_pk);
|
|
||||||
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
fn encaps(
|
|
||||||
&self,
|
|
||||||
shk: &mut [u8; SHK_LEN],
|
|
||||||
ct: &mut [u8; CT_LEN],
|
|
||||||
pk: &[u8; PK_LEN],
|
|
||||||
) -> Result<(), KemError> {
|
|
||||||
let mut randomness = [0u8; libcrux_ml_kem::SHARED_SECRET_SIZE];
|
|
||||||
rand::thread_rng().fill_bytes(&mut randomness);
|
|
||||||
|
|
||||||
let (new_ct, new_shk) = kyber512::encapsulate(&pk.into(), randomness);
|
|
||||||
let new_ct: &[u8; CT_LEN] = new_ct.as_slice();
|
|
||||||
|
|
||||||
shk.clone_from_slice(&new_shk);
|
|
||||||
ct.clone_from_slice(new_ct);
|
|
||||||
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
fn decaps(
|
|
||||||
&self,
|
|
||||||
shk: &mut [u8; SHK_LEN],
|
|
||||||
sk: &[u8; SK_LEN],
|
|
||||||
ct: &[u8; CT_LEN],
|
|
||||||
) -> Result<(), KemError> {
|
|
||||||
let new_shk: [u8; SHK_LEN] = kyber512::decapsulate(&sk.into(), &ct.into());
|
|
||||||
shk.clone_from(&new_shk);
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Default for Kyber512 {
|
|
||||||
fn default() -> Self {
|
|
||||||
Self
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl KemKyber512 for Kyber512 {}
|
|
||||||
|
|
||||||
#[cfg(test)]
|
|
||||||
mod equivalence_tests {
|
|
||||||
use super::*;
|
|
||||||
|
|
||||||
// Test that libcrux and OQS produce the same results
|
|
||||||
#[test]
|
|
||||||
fn proptest_equivalence_libcrux_oqs() {
|
|
||||||
use rosenpass_oqs::Kyber512 as OqsKyber512;
|
|
||||||
|
|
||||||
let (mut sk1, mut pk1) = ([0; SK_LEN], [0; PK_LEN]);
|
|
||||||
let (mut sk2, mut pk2) = ([0; SK_LEN], [0; PK_LEN]);
|
|
||||||
|
|
||||||
let mut ct_left = [0; CT_LEN];
|
|
||||||
let mut ct_right = [0; CT_LEN];
|
|
||||||
|
|
||||||
let mut shk_enc_left = [0; SHK_LEN];
|
|
||||||
let mut shk_enc_right = [0; SHK_LEN];
|
|
||||||
|
|
||||||
// naming schema: shk_dec_{encapsing lib}_{decapsing lib}
|
|
||||||
// should be the same if the encapsing lib was the same.
|
|
||||||
let mut shk_dec_left_left = [0; SHK_LEN];
|
|
||||||
let mut shk_dec_left_right = [0; SHK_LEN];
|
|
||||||
let mut shk_dec_right_left = [0; SHK_LEN];
|
|
||||||
let mut shk_dec_right_right = [0; SHK_LEN];
|
|
||||||
|
|
||||||
for _ in 0..1000 {
|
|
||||||
let sk1 = &mut sk1;
|
|
||||||
let pk1 = &mut pk1;
|
|
||||||
let sk2 = &mut sk2;
|
|
||||||
let pk2 = &mut pk2;
|
|
||||||
|
|
||||||
let ct_left = &mut ct_left;
|
|
||||||
let ct_right = &mut ct_right;
|
|
||||||
|
|
||||||
let shk_enc_left = &mut shk_enc_left;
|
|
||||||
let shk_enc_right = &mut shk_enc_right;
|
|
||||||
|
|
||||||
let shk_dec_left_left = &mut shk_dec_left_left;
|
|
||||||
let shk_dec_left_right = &mut shk_dec_left_right;
|
|
||||||
let shk_dec_right_left = &mut shk_dec_right_left;
|
|
||||||
let shk_dec_right_right = &mut shk_dec_right_right;
|
|
||||||
|
|
||||||
Kyber512.keygen(sk1, pk1).unwrap();
|
|
||||||
Kyber512.keygen(sk2, pk2).unwrap();
|
|
||||||
|
|
||||||
Kyber512.encaps(shk_enc_left, ct_left, pk2).unwrap();
|
|
||||||
OqsKyber512.encaps(shk_enc_right, ct_right, pk2).unwrap();
|
|
||||||
|
|
||||||
Kyber512.decaps(shk_dec_left_left, sk2, ct_left).unwrap();
|
|
||||||
Kyber512.decaps(shk_dec_right_left, sk2, ct_right).unwrap();
|
|
||||||
|
|
||||||
OqsKyber512
|
|
||||||
.decaps(shk_dec_left_right, sk2, ct_left)
|
|
||||||
.unwrap();
|
|
||||||
OqsKyber512
|
|
||||||
.decaps(shk_dec_right_right, sk2, ct_right)
|
|
||||||
.unwrap();
|
|
||||||
|
|
||||||
assert_eq!(shk_enc_left, shk_dec_left_left);
|
|
||||||
assert_eq!(shk_enc_left, shk_dec_left_right);
|
|
||||||
|
|
||||||
assert_eq!(shk_enc_right, shk_dec_right_left);
|
|
||||||
assert_eq!(shk_enc_right, shk_dec_right_right);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,14 +0,0 @@
|
|||||||
//! Implementations backed by libcrux, a verified crypto library.
|
|
||||||
//!
|
|
||||||
//! [Website](https://cryspen.com/libcrux/)
|
|
||||||
//!
|
|
||||||
//! [Github](https://github.com/cryspen/libcrux)
|
|
||||||
|
|
||||||
#[cfg(feature = "experiment_libcrux_define_blake2")]
|
|
||||||
pub mod blake2b;
|
|
||||||
|
|
||||||
#[cfg(feature = "experiment_libcrux_define_chachapoly")]
|
|
||||||
pub mod chacha20poly1305_ietf;
|
|
||||||
|
|
||||||
#[cfg(feature = "experiment_libcrux_define_kyber")]
|
|
||||||
pub mod kyber512;
|
|
||||||
@@ -1,16 +1,7 @@
|
|||||||
//! Contains the implementations of the crypto algorithms used throughout Rosenpass.
|
pub mod blake2b;
|
||||||
|
#[cfg(not(feature = "experiment_libcrux"))]
|
||||||
pub mod keyed_hash;
|
pub mod chacha20poly1305_ietf;
|
||||||
|
#[cfg(feature = "experiment_libcrux")]
|
||||||
pub use custom::incorrect_hmac_blake2b;
|
pub mod chacha20poly1305_ietf_libcrux;
|
||||||
pub use rust_crypto::{blake2b, keyed_shake256};
|
pub mod incorrect_hmac_blake2b;
|
||||||
|
pub mod xchacha20poly1305_ietf;
|
||||||
pub mod custom;
|
|
||||||
pub mod rust_crypto;
|
|
||||||
|
|
||||||
#[cfg(any(
|
|
||||||
feature = "experiment_libcrux_define_blake2",
|
|
||||||
feature = "experiment_libcrux_define_chachapoly",
|
|
||||||
feature = "experiment_libcrux_define_kyber",
|
|
||||||
))]
|
|
||||||
pub mod libcrux;
|
|
||||||
|
|||||||
@@ -1,44 +0,0 @@
|
|||||||
use zeroize::Zeroizing;
|
|
||||||
|
|
||||||
use blake2::digest::crypto_common::generic_array::GenericArray;
|
|
||||||
use blake2::digest::crypto_common::typenum::U32;
|
|
||||||
use blake2::digest::{FixedOutput, Mac};
|
|
||||||
use blake2::Blake2bMac;
|
|
||||||
|
|
||||||
use rosenpass_cipher_traits::primitives::KeyedHash;
|
|
||||||
use rosenpass_to::{ops::copy_slice, To};
|
|
||||||
|
|
||||||
pub use rosenpass_cipher_traits::algorithms::keyed_hash_blake2b::{HASH_LEN, KEY_LEN};
|
|
||||||
|
|
||||||
/// Specify that the used implementation of BLAKE2b is the MAC version of BLAKE2b
|
|
||||||
/// with output and key length of 32 bytes (see [Blake2bMac]).
|
|
||||||
type Impl = Blake2bMac<U32>;
|
|
||||||
|
|
||||||
/// Hashes the given `data` with the [Blake2bMac] hash function under the given `key`.
|
|
||||||
/// The both the length of the output the length of the key 32 bytes (or 256 bits).
|
|
||||||
pub struct Blake2b;
|
|
||||||
|
|
||||||
impl KeyedHash<KEY_LEN, HASH_LEN> for Blake2b {
|
|
||||||
type Error = anyhow::Error;
|
|
||||||
|
|
||||||
fn keyed_hash(
|
|
||||||
key: &[u8; KEY_LEN],
|
|
||||||
data: &[u8],
|
|
||||||
out: &mut [u8; HASH_LEN],
|
|
||||||
) -> Result<(), Self::Error> {
|
|
||||||
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; HASH_LEN]);
|
|
||||||
let tmp = GenericArray::from_mut_slice(tmp.as_mut());
|
|
||||||
h.finalize_into(tmp);
|
|
||||||
copy_slice(tmp.as_ref()).to(out);
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl rosenpass_cipher_traits::algorithms::KeyedHashBlake2b for Blake2b {}
|
|
||||||
@@ -1,79 +0,0 @@
|
|||||||
use rosenpass_to::ops::copy_slice;
|
|
||||||
use rosenpass_to::To;
|
|
||||||
|
|
||||||
use rosenpass_cipher_traits::algorithms::AeadChaCha20Poly1305;
|
|
||||||
use rosenpass_cipher_traits::primitives::{Aead, AeadError};
|
|
||||||
|
|
||||||
use chacha20poly1305::aead::generic_array::GenericArray;
|
|
||||||
use chacha20poly1305::ChaCha20Poly1305 as AeadImpl;
|
|
||||||
use chacha20poly1305::{AeadInPlace, KeyInit};
|
|
||||||
|
|
||||||
pub use rosenpass_cipher_traits::algorithms::aead_chacha20poly1305::{KEY_LEN, NONCE_LEN, TAG_LEN};
|
|
||||||
|
|
||||||
/// Implements the [`Aead`] and [`AeadChaCha20Poly1305`] traits backed by the RustCrypto
|
|
||||||
/// implementation.
|
|
||||||
pub struct ChaCha20Poly1305;
|
|
||||||
|
|
||||||
impl Aead<KEY_LEN, NONCE_LEN, TAG_LEN> for ChaCha20Poly1305 {
|
|
||||||
fn encrypt(
|
|
||||||
&self,
|
|
||||||
ciphertext: &mut [u8],
|
|
||||||
key: &[u8; KEY_LEN],
|
|
||||||
nonce: &[u8; NONCE_LEN],
|
|
||||||
ad: &[u8],
|
|
||||||
plaintext: &[u8],
|
|
||||||
) -> Result<(), AeadError> {
|
|
||||||
// The comparison looks complicated, but we need to do it this way to prevent
|
|
||||||
// over/underflows.
|
|
||||||
if ciphertext.len() < TAG_LEN || ciphertext.len() - TAG_LEN < plaintext.len() {
|
|
||||||
return Err(AeadError::InvalidLengths);
|
|
||||||
}
|
|
||||||
|
|
||||||
let nonce = GenericArray::from_slice(nonce);
|
|
||||||
let (ct, mac) = ciphertext.split_at_mut(ciphertext.len() - TAG_LEN);
|
|
||||||
copy_slice(plaintext).to(ct);
|
|
||||||
|
|
||||||
// This only fails if the length is wrong, which really shouldn't happen and would
|
|
||||||
// constitute an internal error.
|
|
||||||
let encrypter = AeadImpl::new_from_slice(key).map_err(|_| AeadError::InternalError)?;
|
|
||||||
|
|
||||||
let mac_value = encrypter
|
|
||||||
.encrypt_in_place_detached(nonce, ad, ct)
|
|
||||||
.map_err(|_| AeadError::InternalError)?;
|
|
||||||
copy_slice(&mac_value[..]).to(mac);
|
|
||||||
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
fn decrypt(
|
|
||||||
&self,
|
|
||||||
plaintext: &mut [u8],
|
|
||||||
key: &[u8; KEY_LEN],
|
|
||||||
nonce: &[u8; NONCE_LEN],
|
|
||||||
ad: &[u8],
|
|
||||||
ciphertext: &[u8],
|
|
||||||
) -> Result<(), AeadError> {
|
|
||||||
// The comparison looks complicated, but we need to do it this way to prevent
|
|
||||||
// over/underflows.
|
|
||||||
if ciphertext.len() < TAG_LEN || ciphertext.len() - TAG_LEN < plaintext.len() {
|
|
||||||
return Err(AeadError::InvalidLengths);
|
|
||||||
}
|
|
||||||
|
|
||||||
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);
|
|
||||||
|
|
||||||
// This only fails if the length is wrong, which really shouldn't happen and would
|
|
||||||
// constitute an internal error.
|
|
||||||
let decrypter = AeadImpl::new_from_slice(key).map_err(|_| AeadError::InternalError)?;
|
|
||||||
|
|
||||||
decrypter
|
|
||||||
.decrypt_in_place_detached(nonce, ad, plaintext, tag)
|
|
||||||
.map_err(|_| AeadError::DecryptError)?;
|
|
||||||
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl AeadChaCha20Poly1305 for ChaCha20Poly1305 {}
|
|
||||||
@@ -1,117 +0,0 @@
|
|||||||
use anyhow::ensure;
|
|
||||||
use rosenpass_cipher_traits::primitives::{InferKeyedHash, KeyedHash};
|
|
||||||
use sha3::digest::{ExtendableOutput, Update, XofReader};
|
|
||||||
use sha3::Shake256;
|
|
||||||
|
|
||||||
pub use rosenpass_cipher_traits::algorithms::keyed_hash_shake256::{HASH_LEN, KEY_LEN};
|
|
||||||
|
|
||||||
/// An implementation of the [`KeyedHash`] trait backed by the RustCrypto implementation of SHAKE256.
|
|
||||||
#[derive(Clone, Debug, PartialEq, Eq)]
|
|
||||||
pub struct SHAKE256Core<const KEY_LEN: usize, const HASH_LEN: usize>;
|
|
||||||
|
|
||||||
impl<const KEY_LEN: usize, const HASH_LEN: usize> KeyedHash<KEY_LEN, HASH_LEN>
|
|
||||||
for SHAKE256Core<KEY_LEN, HASH_LEN>
|
|
||||||
{
|
|
||||||
type Error = anyhow::Error;
|
|
||||||
|
|
||||||
/// Provides a keyed hash function based on SHAKE256. To work for the protocol, the output length
|
|
||||||
/// and key length are fixed to 32 bytes (also see [KEY_LEN] and [HASH_LEN]).
|
|
||||||
///
|
|
||||||
/// Note that the SHAKE256 is designed for 64 bytes output length, which we truncate to 32 bytes
|
|
||||||
/// to work well with the overall protocol. Referring to Table 4 of FIPS 202, this offers the
|
|
||||||
/// same collision resistance as SHAKE128, but 256 bits of preimage resistance. We therefore
|
|
||||||
/// prefer a truncated SHAKE256 over SHAKE128.
|
|
||||||
///
|
|
||||||
/// #Examples
|
|
||||||
/// ```rust
|
|
||||||
/// # use rosenpass_ciphers::subtle::rust_crypto::keyed_shake256::SHAKE256Core;
|
|
||||||
/// use rosenpass_cipher_traits::primitives::KeyedHash;
|
|
||||||
/// const KEY_LEN: usize = 32;
|
|
||||||
/// const HASH_LEN: usize = 32;
|
|
||||||
/// let key: [u8; 32] = [0; KEY_LEN];
|
|
||||||
/// let data: [u8; 32] = [255; 32]; // arbitrary data, could also be longer
|
|
||||||
/// // buffer for the hash output
|
|
||||||
/// let mut hash_data: [u8; 32] = [0u8; HASH_LEN];
|
|
||||||
///
|
|
||||||
/// assert!(SHAKE256Core::<32, 32>::keyed_hash(&key, &data, &mut hash_data).is_ok(), "Hashing has to return OK result");
|
|
||||||
/// # let expected_hash: &[u8] = &[174, 4, 47, 188, 1, 228, 179, 246, 67, 43, 255, 94, 155, 11,
|
|
||||||
/// 187, 161, 38, 110, 217, 23, 4, 62, 172, 30, 218, 187, 249, 80, 171, 21, 145, 238];
|
|
||||||
/// # assert_eq!(hash_data, expected_hash);
|
|
||||||
/// ```
|
|
||||||
fn keyed_hash(
|
|
||||||
key: &[u8; KEY_LEN],
|
|
||||||
data: &[u8],
|
|
||||||
out: &mut [u8; HASH_LEN],
|
|
||||||
) -> Result<(), Self::Error> {
|
|
||||||
// Since SHAKE256 is a XOF, we fix the output length manually to what is required for the
|
|
||||||
// protocol.
|
|
||||||
ensure!(out.len() == HASH_LEN);
|
|
||||||
// Not bothering with padding; the implementation
|
|
||||||
// uses appropriately sized keys.
|
|
||||||
ensure!(key.len() == KEY_LEN);
|
|
||||||
let mut shake256 = Shake256::default();
|
|
||||||
shake256.update(key);
|
|
||||||
shake256.update(data);
|
|
||||||
|
|
||||||
// Since we use domain separation extensively, related outputs of the truncated XOF
|
|
||||||
// are not a concern. This follows the NIST recommendations in Section A.2 of the FIPS 202
|
|
||||||
// standard, (pages 24/25, i.e., 32/33 in the PDF).
|
|
||||||
shake256.finalize_xof().read(out);
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<const KEY_LEN: usize, const HASH_LEN: usize> SHAKE256Core<KEY_LEN, HASH_LEN> {
|
|
||||||
pub fn new() -> Self {
|
|
||||||
Self
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<const KEY_LEN: usize, const HASH_LEN: usize> Default for SHAKE256Core<KEY_LEN, HASH_LEN> {
|
|
||||||
fn default() -> Self {
|
|
||||||
Self::new()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// This type provides the same functionality as [SHAKE256Core], but bound to an instance.
|
|
||||||
/// In contrast to [SHAKE256Core], this allows for type interference and thus allows the user of the
|
|
||||||
/// type to omit explicit type parameters when instantiating the type or using it.
|
|
||||||
///
|
|
||||||
/// The instantiation is based on the [InferKeyedHash] trait.
|
|
||||||
///
|
|
||||||
/// ```rust
|
|
||||||
/// # use rosenpass_ciphers::subtle::rust_crypto::keyed_shake256::{SHAKE256};
|
|
||||||
/// use rosenpass_cipher_traits::primitives::KeyedHashInstance;
|
|
||||||
/// const KEY_LEN: usize = 32;
|
|
||||||
/// const HASH_LEN: usize = 32;
|
|
||||||
/// let key: [u8; KEY_LEN] = [0; KEY_LEN];
|
|
||||||
/// let data: [u8; 32] = [255; 32]; // arbitrary data, could also be longer
|
|
||||||
/// // buffer for the hash output
|
|
||||||
/// let mut hash_data: [u8; 32] = [0u8; HASH_LEN];
|
|
||||||
/// assert!(SHAKE256::new().keyed_hash(&key, &data, &mut hash_data).is_ok(), "Hashing has to return OK result");
|
|
||||||
/// # let expected_hash: &[u8] = &[174, 4, 47, 188, 1, 228, 179, 246, 67, 43, 255, 94, 155, 11, 187,
|
|
||||||
/// 161, 38, 110, 217, 23, 4, 62, 172, 30, 218, 187, 249, 80, 171, 21, 145, 238];
|
|
||||||
/// # assert_eq!(hash_data, expected_hash);
|
|
||||||
/// ```
|
|
||||||
pub type SHAKE256<const KEY_LEN: usize, const HASH_LEN: usize> =
|
|
||||||
InferKeyedHash<SHAKE256Core<KEY_LEN, HASH_LEN>, KEY_LEN, HASH_LEN>;
|
|
||||||
|
|
||||||
/// The SHAKE256_32 type is a specific instance of the [SHAKE256] type with the key length and hash
|
|
||||||
/// length fixed to 32 bytes.
|
|
||||||
///
|
|
||||||
/// ```rust
|
|
||||||
/// # use rosenpass_ciphers::subtle::keyed_shake256::{SHAKE256_32};
|
|
||||||
/// use rosenpass_cipher_traits::primitives::KeyedHashInstance;
|
|
||||||
/// const KEY_LEN: usize = 32;
|
|
||||||
/// const HASH_LEN: usize = 32;
|
|
||||||
/// let key: [u8; 32] = [0; KEY_LEN];
|
|
||||||
/// let data: [u8; 32] = [255; 32]; // arbitrary data, could also be longer
|
|
||||||
/// // buffer for the hash output
|
|
||||||
/// let mut hash_data: [u8; 32] = [0u8; HASH_LEN];
|
|
||||||
///
|
|
||||||
/// assert!(SHAKE256_32::new().keyed_hash(&key, &data, &mut hash_data).is_ok(), "Hashing has to return OK result");
|
|
||||||
/// # let expected_hash: &[u8] = &[174, 4, 47, 188, 1, 228, 179, 246, 67, 43, 255, 94, 155, 11, 187,
|
|
||||||
/// 161, 38, 110, 217, 23, 4, 62, 172, 30, 218, 187, 249, 80, 171, 21, 145, 238];
|
|
||||||
/// # assert_eq!(hash_data, expected_hash);
|
|
||||||
/// ```
|
|
||||||
pub type SHAKE256_32 = SHAKE256<32, 32>;
|
|
||||||
@@ -1,7 +0,0 @@
|
|||||||
//! Implementations backed by RustCrypto
|
|
||||||
|
|
||||||
pub mod blake2b;
|
|
||||||
pub mod keyed_shake256;
|
|
||||||
|
|
||||||
pub mod chacha20poly1305_ietf;
|
|
||||||
pub mod xchacha20poly1305_ietf;
|
|
||||||
@@ -1,164 +0,0 @@
|
|||||||
use rosenpass_to::ops::copy_slice;
|
|
||||||
use rosenpass_to::To;
|
|
||||||
|
|
||||||
use rosenpass_cipher_traits::algorithms::aead_xchacha20poly1305::AeadXChaCha20Poly1305;
|
|
||||||
use rosenpass_cipher_traits::primitives::{Aead, AeadError, AeadWithNonceInCiphertext};
|
|
||||||
|
|
||||||
use chacha20poly1305::aead::generic_array::GenericArray;
|
|
||||||
use chacha20poly1305::XChaCha20Poly1305 as AeadImpl;
|
|
||||||
use chacha20poly1305::{AeadInPlace, KeyInit};
|
|
||||||
|
|
||||||
pub use rosenpass_cipher_traits::algorithms::aead_xchacha20poly1305::{
|
|
||||||
KEY_LEN, NONCE_LEN, TAG_LEN,
|
|
||||||
};
|
|
||||||
/// Implements the [`Aead`] and [`AeadXChaCha20Poly1305`] traits backed by the RustCrypto
|
|
||||||
/// implementation.
|
|
||||||
pub struct XChaCha20Poly1305;
|
|
||||||
|
|
||||||
impl Aead<KEY_LEN, NONCE_LEN, TAG_LEN> for XChaCha20Poly1305 {
|
|
||||||
fn encrypt(
|
|
||||||
&self,
|
|
||||||
ciphertext: &mut [u8],
|
|
||||||
key: &[u8; KEY_LEN],
|
|
||||||
nonce: &[u8; NONCE_LEN],
|
|
||||||
ad: &[u8],
|
|
||||||
plaintext: &[u8],
|
|
||||||
) -> Result<(), AeadError> {
|
|
||||||
// The comparison looks complicated, but we need to do it this way to prevent
|
|
||||||
// over/underflows.
|
|
||||||
if ciphertext.len() < TAG_LEN || ciphertext.len() - TAG_LEN < plaintext.len() {
|
|
||||||
return Err(AeadError::InvalidLengths);
|
|
||||||
}
|
|
||||||
|
|
||||||
let (ct, mac) = ciphertext.split_at_mut(ciphertext.len() - TAG_LEN);
|
|
||||||
copy_slice(plaintext).to(ct);
|
|
||||||
|
|
||||||
let nonce = GenericArray::from_slice(nonce);
|
|
||||||
|
|
||||||
// This only fails if the length is wrong, which really shouldn't happen and would
|
|
||||||
// constitute an internal error.
|
|
||||||
let encrypter = AeadImpl::new_from_slice(key).map_err(|_| AeadError::InternalError)?;
|
|
||||||
|
|
||||||
let mac_value = encrypter
|
|
||||||
.encrypt_in_place_detached(nonce, ad, ct)
|
|
||||||
.map_err(|_| AeadError::InternalError)?;
|
|
||||||
copy_slice(&mac_value[..]).to(mac);
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
fn decrypt(
|
|
||||||
&self,
|
|
||||||
plaintext: &mut [u8],
|
|
||||||
key: &[u8; KEY_LEN],
|
|
||||||
nonce: &[u8; NONCE_LEN],
|
|
||||||
ad: &[u8],
|
|
||||||
ciphertext: &[u8],
|
|
||||||
) -> Result<(), AeadError> {
|
|
||||||
// The comparison looks complicated, but we need to do it this way to prevent
|
|
||||||
// over/underflows.
|
|
||||||
if ciphertext.len() < TAG_LEN || ciphertext.len() - TAG_LEN < plaintext.len() {
|
|
||||||
return Err(AeadError::InvalidLengths);
|
|
||||||
}
|
|
||||||
|
|
||||||
let (ct, mac) = ciphertext.split_at(ciphertext.len() - TAG_LEN);
|
|
||||||
let nonce = GenericArray::from_slice(nonce);
|
|
||||||
let tag = GenericArray::from_slice(mac);
|
|
||||||
copy_slice(ct).to(plaintext);
|
|
||||||
|
|
||||||
// This only fails if the length is wrong, which really shouldn't happen and would
|
|
||||||
// constitute an internal error.
|
|
||||||
let decrypter = AeadImpl::new_from_slice(key).map_err(|_| AeadError::InternalError)?;
|
|
||||||
|
|
||||||
decrypter
|
|
||||||
.decrypt_in_place_detached(nonce, ad, plaintext, tag)
|
|
||||||
.map_err(|_| AeadError::DecryptError)?;
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl AeadXChaCha20Poly1305 for XChaCha20Poly1305 {}
|
|
||||||
|
|
||||||
/// 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::rust_crypto::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; KEY_LEN] = &[0u8; KEY_LEN]; // THIS IS NOT A SECURE KEY
|
|
||||||
/// let nonce: &[u8; NONCE_LEN] = &[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; KEY_LEN],
|
|
||||||
nonce: &[u8; NONCE_LEN],
|
|
||||||
ad: &[u8],
|
|
||||||
plaintext: &[u8],
|
|
||||||
) -> anyhow::Result<()> {
|
|
||||||
XChaCha20Poly1305
|
|
||||||
.encrypt_with_nonce_in_ctxt(ciphertext, key, nonce, ad, plaintext)
|
|
||||||
.map_err(anyhow::Error::from)
|
|
||||||
}
|
|
||||||
|
|
||||||
/// 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::rust_crypto::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; KEY_LEN] = &[0u8; KEY_LEN]; // THIS IS NOT A SECURE KEY
|
|
||||||
/// let nonce: &[u8; NONCE_LEN] = &[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; KEY_LEN],
|
|
||||||
ad: &[u8],
|
|
||||||
ciphertext: &[u8],
|
|
||||||
) -> anyhow::Result<()> {
|
|
||||||
XChaCha20Poly1305
|
|
||||||
.decrypt_with_nonce_in_ctxt(plaintext, key, ad, ciphertext)
|
|
||||||
.map_err(anyhow::Error::from)
|
|
||||||
}
|
|
||||||
45
ciphers/src/subtle/xchacha20poly1305_ietf.rs
Normal file
@@ -0,0 +1,45 @@
|
|||||||
|
use rosenpass_to::ops::copy_slice;
|
||||||
|
use rosenpass_to::To;
|
||||||
|
use rosenpass_util::typenum2const;
|
||||||
|
|
||||||
|
use chacha20poly1305::aead::generic_array::GenericArray;
|
||||||
|
use chacha20poly1305::XChaCha20Poly1305 as AeadImpl;
|
||||||
|
use chacha20poly1305::{AeadCore, AeadInPlace, KeyInit, KeySizeUser};
|
||||||
|
|
||||||
|
pub const KEY_LEN: usize = typenum2const! { <AeadImpl as KeySizeUser>::KeySize };
|
||||||
|
pub const TAG_LEN: usize = typenum2const! { <AeadImpl as AeadCore>::TagSize };
|
||||||
|
pub const NONCE_LEN: usize = typenum2const! { <AeadImpl as AeadCore>::NonceSize };
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
pub fn encrypt(
|
||||||
|
ciphertext: &mut [u8],
|
||||||
|
key: &[u8],
|
||||||
|
nonce: &[u8],
|
||||||
|
ad: &[u8],
|
||||||
|
plaintext: &[u8],
|
||||||
|
) -> anyhow::Result<()> {
|
||||||
|
let nonce = GenericArray::from_slice(nonce);
|
||||||
|
let (n, ct_mac) = ciphertext.split_at_mut(NONCE_LEN);
|
||||||
|
let (ct, mac) = ct_mac.split_at_mut(ct_mac.len() - TAG_LEN);
|
||||||
|
copy_slice(nonce).to(n);
|
||||||
|
copy_slice(plaintext).to(ct);
|
||||||
|
let mac_value = AeadImpl::new_from_slice(key)?.encrypt_in_place_detached(nonce, ad, ct)?;
|
||||||
|
copy_slice(&mac_value[..]).to(mac);
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
pub fn decrypt(
|
||||||
|
plaintext: &mut [u8],
|
||||||
|
key: &[u8],
|
||||||
|
ad: &[u8],
|
||||||
|
ciphertext: &[u8],
|
||||||
|
) -> anyhow::Result<()> {
|
||||||
|
let (n, ct_mac) = ciphertext.split_at(NONCE_LEN);
|
||||||
|
let (ct, mac) = ct_mac.split_at(ct_mac.len() - TAG_LEN);
|
||||||
|
let nonce = GenericArray::from_slice(n);
|
||||||
|
let tag = GenericArray::from_slice(mac);
|
||||||
|
copy_slice(ct).to(plaintext);
|
||||||
|
AeadImpl::new_from_slice(key)?.decrypt_in_place_detached(nonce, ad, plaintext, tag)?;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
@@ -8,7 +8,6 @@ description = "Rosenpass internal utilities for constant time crypto implementat
|
|||||||
homepage = "https://rosenpass.eu/"
|
homepage = "https://rosenpass.eu/"
|
||||||
repository = "https://github.com/rosenpass/rosenpass"
|
repository = "https://github.com/rosenpass/rosenpass"
|
||||||
readme = "readme.md"
|
readme = "readme.md"
|
||||||
rust-version = "1.77.0"
|
|
||||||
|
|
||||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||||
|
|
||||||
@@ -20,7 +19,4 @@ rosenpass-to = { workspace = true }
|
|||||||
memsec = { workspace = true }
|
memsec = { workspace = true }
|
||||||
|
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
rand = { workspace = true }
|
rand = "0.8.5"
|
||||||
|
|
||||||
[lints.rust]
|
|
||||||
unexpected_cfgs = { level = "allow", check-cfg = ['cfg(coverage)'] }
|
|
||||||
|
|||||||
@@ -2,29 +2,14 @@
|
|||||||
|
|
||||||
use core::ptr;
|
use core::ptr;
|
||||||
|
|
||||||
/// Little endian memcmp version of [quinier/memsec](https://github.com/quininer/memsec/blob/bbc647967ff6d20d6dccf1c85f5d9037fcadd3b0/src/lib.rs#L30)
|
/// Little endian memcmp version of quinier/memsec
|
||||||
|
/// https://github.com/quininer/memsec/blob/bbc647967ff6d20d6dccf1c85f5d9037fcadd3b0/src/lib.rs#L30
|
||||||
///
|
///
|
||||||
/// # Panic & Safety
|
/// # Panic & Safety
|
||||||
///
|
///
|
||||||
/// Both input arrays must be at least of the indicated length.
|
/// Both input arrays must be at least of the indicated length.
|
||||||
///
|
///
|
||||||
/// See [std::ptr::read_volatile] on safety.
|
/// See [std::ptr::read_volatile] on safety.
|
||||||
///
|
|
||||||
/// # Examples
|
|
||||||
/// ```
|
|
||||||
/// let a = [1, 2, 3, 4];
|
|
||||||
/// let b = [1, 2, 3, 4];
|
|
||||||
/// let c = [1, 2, 2, 5];
|
|
||||||
/// let d = [1, 2, 2, 4];
|
|
||||||
///
|
|
||||||
/// unsafe {
|
|
||||||
/// use rosenpass_constant_time::memcmp_le;
|
|
||||||
/// assert_eq!(memcmp_le(a.as_ptr(), b.as_ptr(), 4), 0);
|
|
||||||
/// assert!(memcmp_le(a.as_ptr(), c.as_ptr(), 4) < 0);
|
|
||||||
/// assert!(memcmp_le(a.as_ptr(), d.as_ptr(), 4) > 0);
|
|
||||||
/// assert_eq!(memcmp_le(a.as_ptr(), b.as_ptr(), 2), 0);
|
|
||||||
/// }
|
|
||||||
/// ```
|
|
||||||
#[inline(never)]
|
#[inline(never)]
|
||||||
pub unsafe fn memcmp_le(b1: *const u8, b2: *const u8, len: usize) -> i32 {
|
pub unsafe fn memcmp_le(b1: *const u8, b2: *const u8, len: usize) -> i32 {
|
||||||
let mut res = 0;
|
let mut res = 0;
|
||||||
@@ -92,23 +77,3 @@ pub fn compare(a: &[u8], b: &[u8]) -> i32 {
|
|||||||
assert!(a.len() == b.len());
|
assert!(a.len() == b.len());
|
||||||
unsafe { memcmp_le(a.as_ptr(), b.as_ptr(), a.len()) }
|
unsafe { memcmp_le(a.as_ptr(), b.as_ptr(), a.len()) }
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
|
||||||
mod tests {
|
|
||||||
use crate::compare::memcmp_le;
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn memcmp_le_test() {
|
|
||||||
let a = [1, 2, 3, 4];
|
|
||||||
let b = [1, 2, 3, 4];
|
|
||||||
let c = [1, 2, 2, 5];
|
|
||||||
let d = [1, 2, 2, 4];
|
|
||||||
|
|
||||||
unsafe {
|
|
||||||
assert_eq!(memcmp_le(a.as_ptr(), b.as_ptr(), 4), 0);
|
|
||||||
assert!(memcmp_le(a.as_ptr(), c.as_ptr(), 4) < 0);
|
|
||||||
assert!(memcmp_le(a.as_ptr(), d.as_ptr(), 4) > 0);
|
|
||||||
assert_eq!(memcmp_le(a.as_ptr(), b.as_ptr(), 2), 0);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -6,16 +6,8 @@ use core::hint::black_box;
|
|||||||
/// and increment that integer.
|
/// and increment that integer.
|
||||||
///
|
///
|
||||||
/// # Leaks
|
/// # Leaks
|
||||||
/// This function may leak timing information in the following ways:
|
/// TODO: mention here if this function leaks any information, see
|
||||||
///
|
/// <https://github.com/rosenpass/rosenpass/issues/232>
|
||||||
/// - The function execution time is linearly proportional to the input length
|
|
||||||
/// - The number of carry operations that occur may affect timing slightly
|
|
||||||
/// - Memory access patterns are sequential and predictable
|
|
||||||
///
|
|
||||||
/// The carry operation timing variation is mitigated through the use of black_box,
|
|
||||||
/// but the linear scaling with input size is inherent to the operation.
|
|
||||||
/// These timing characteristics are generally considered acceptable for most
|
|
||||||
/// cryptographic counter implementations.
|
|
||||||
///
|
///
|
||||||
/// ## Tests
|
/// ## Tests
|
||||||
/// For discussion on how to ensure the constant-time execution of this function, see
|
/// For discussion on how to ensure the constant-time execution of this function, see
|
||||||
|
|||||||
@@ -7,32 +7,6 @@
|
|||||||
//! ## TODO
|
//! ## TODO
|
||||||
//! Figure out methodology to ensure that code is actually constant time, see
|
//! Figure out methodology to ensure that code is actually constant time, see
|
||||||
//! <https://github.com/rosenpass/rosenpass/issues/232>
|
//! <https://github.com/rosenpass/rosenpass/issues/232>
|
||||||
//!
|
|
||||||
//! # Examples
|
|
||||||
//!
|
|
||||||
//! ```rust
|
|
||||||
//! use rosenpass_constant_time::{memcmp, compare};
|
|
||||||
//!
|
|
||||||
//! let a = [1, 2, 3, 4];
|
|
||||||
//! let b = [1, 2, 3, 4];
|
|
||||||
//! let c = [1, 2, 3, 5];
|
|
||||||
//!
|
|
||||||
//! // Compare for equality
|
|
||||||
//! assert!(memcmp(&a, &b));
|
|
||||||
//! assert!(!memcmp(&a, &c));
|
|
||||||
//!
|
|
||||||
//! // Compare lexicographically
|
|
||||||
//! assert_eq!(compare(&a, &c), -1); // a < c
|
|
||||||
//! assert_eq!(compare(&c, &a), 1); // c > a
|
|
||||||
//! assert_eq!(compare(&a, &b), 0); // a == b
|
|
||||||
//! ```
|
|
||||||
//!
|
|
||||||
//! # Security Notes
|
|
||||||
//!
|
|
||||||
//! While these functions aim to be constant-time, they may leak timing information in some cases:
|
|
||||||
//!
|
|
||||||
//! - Length mismatches between inputs are immediately detectable
|
|
||||||
//! - Execution time scales linearly with input size
|
|
||||||
|
|
||||||
mod compare;
|
mod compare;
|
||||||
mod increment;
|
mod increment;
|
||||||
@@ -40,7 +14,6 @@ mod memcmp;
|
|||||||
mod xor;
|
mod xor;
|
||||||
|
|
||||||
pub use compare::compare;
|
pub use compare::compare;
|
||||||
pub use compare::memcmp_le;
|
|
||||||
pub use increment::increment;
|
pub use increment::increment;
|
||||||
pub use memcmp::memcmp;
|
pub use memcmp::memcmp;
|
||||||
pub use xor::xor;
|
pub use xor::xor;
|
||||||
|
|||||||
@@ -32,11 +32,8 @@ pub fn memcmp(a: &[u8], b: &[u8]) -> bool {
|
|||||||
/// For discussion on how to (further) ensure the constant-time execution of this function,
|
/// For discussion on how to (further) ensure the constant-time execution of this function,
|
||||||
/// see <https://github.com/rosenpass/rosenpass/issues/232>
|
/// see <https://github.com/rosenpass/rosenpass/issues/232>
|
||||||
#[cfg(all(test, feature = "constant_time_tests"))]
|
#[cfg(all(test, feature = "constant_time_tests"))]
|
||||||
// Stopgap measure against https://github.com/rosenpass/rosenpass/issues/634
|
|
||||||
#[cfg(not(all(target_os = "macos", target_arch = "aarch64")))]
|
|
||||||
mod tests {
|
mod tests {
|
||||||
use super::*;
|
use super::*;
|
||||||
use core::hint::black_box;
|
|
||||||
use rand::seq::SliceRandom;
|
use rand::seq::SliceRandom;
|
||||||
use rand::thread_rng;
|
use rand::thread_rng;
|
||||||
use std::time::Instant;
|
use std::time::Instant;
|
||||||
@@ -53,12 +50,14 @@ mod tests {
|
|||||||
fn memcmp_runs_in_constant_time() {
|
fn memcmp_runs_in_constant_time() {
|
||||||
// prepare data to compare
|
// prepare data to compare
|
||||||
let n: usize = 1E6 as usize; // number of comparisons to run
|
let n: usize = 1E6 as usize; // number of comparisons to run
|
||||||
const LEN: usize = 1024; // length of each slice passed as parameters to the tested comparison function
|
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 a = [b'a'; LEN];
|
let a1 = a1.as_bytes();
|
||||||
let b = [b'b'; LEN];
|
let a2 = a2.as_bytes();
|
||||||
|
let b = b.as_bytes();
|
||||||
let mut tmp = [0u8; LEN];
|
|
||||||
|
|
||||||
// vector representing all timing tests
|
// vector representing all timing tests
|
||||||
//
|
//
|
||||||
@@ -72,14 +71,12 @@ mod tests {
|
|||||||
|
|
||||||
// run comparisons / call function to test
|
// run comparisons / call function to test
|
||||||
for test in tests.iter_mut() {
|
for test in tests.iter_mut() {
|
||||||
let src = match test.0 {
|
|
||||||
true => a,
|
|
||||||
false => b,
|
|
||||||
};
|
|
||||||
tmp.copy_from_slice(&src);
|
|
||||||
|
|
||||||
let now = Instant::now();
|
let now = Instant::now();
|
||||||
memcmp(black_box(&a), black_box(&tmp));
|
if test.0 {
|
||||||
|
memcmp(a1, a2);
|
||||||
|
} else {
|
||||||
|
memcmp(a1, b);
|
||||||
|
}
|
||||||
test.1 = now.elapsed();
|
test.1 = now.elapsed();
|
||||||
// println!("eq: {}, elapsed: {:.2?}", test.0, test.1);
|
// println!("eq: {}, elapsed: {:.2?}", test.0, test.1);
|
||||||
}
|
}
|
||||||
@@ -116,7 +113,6 @@ mod tests {
|
|||||||
// Pearson correlation
|
// Pearson correlation
|
||||||
let correlation = cv / (sd_x * sd_y);
|
let correlation = cv / (sd_x * sd_y);
|
||||||
println!("correlation: {:.6?}", correlation);
|
println!("correlation: {:.6?}", correlation);
|
||||||
#[cfg(not(coverage))]
|
|
||||||
assert!(
|
assert!(
|
||||||
correlation.abs() < 0.01,
|
correlation.abs() < 0.01,
|
||||||
"execution time correlates with result"
|
"execution time correlates with result"
|
||||||
|
|||||||
@@ -5,23 +5,12 @@ use rosenpass_to::{with_destination, To};
|
|||||||
|
|
||||||
/// Xors the source into the destination
|
/// Xors the source into the destination
|
||||||
///
|
///
|
||||||
/// Performs a constant-time XOR operation between two byte slices
|
|
||||||
///
|
|
||||||
/// Takes a source slice and XORs it with the destination slice in-place using the
|
|
||||||
/// rosenpass_to trait for destination management.
|
|
||||||
///
|
|
||||||
/// # Panics
|
/// # Panics
|
||||||
/// If source and destination are of different sizes.
|
/// If source and destination are of different sizes.
|
||||||
///
|
///
|
||||||
/// # Leaks
|
/// # Leaks
|
||||||
/// This function may leak timing information in the following ways:
|
/// TODO: mention here if this function leaks any information, see
|
||||||
///
|
/// <https://github.com/rosenpass/rosenpass/issues/232>
|
||||||
/// - The function execution time is linearly proportional to the input length
|
|
||||||
/// - Length mismatches between source and destination are immediately detectable via panic
|
|
||||||
/// - Memory access patterns follow a predictable sequential pattern
|
|
||||||
///
|
|
||||||
/// These leaks are generally considered acceptable in most cryptographic contexts
|
|
||||||
/// as they don't reveal information about the actual content being XORed.
|
|
||||||
///
|
///
|
||||||
/// ## Tests
|
/// ## Tests
|
||||||
/// For discussion on how to ensure the constant-time execution of this function, see
|
/// For discussion on how to ensure the constant-time execution of this function, see
|
||||||
|
|||||||
@@ -1,46 +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 --branch
|
|
||||||
|
|
||||||
exc rm -rf target/llvm-cov-target/debug/deps/doctestbins
|
|
||||||
exc mv -v target/llvm-cov-target/doctestbins target/llvm-cov-target/debug/deps/
|
|
||||||
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 "$@"
|
|
||||||
121
deny.toml
@@ -1,121 +0,0 @@
|
|||||||
# The graph table configures how the dependency graph is constructed and thus
|
|
||||||
# which crates the checks are performed against
|
|
||||||
[graph]
|
|
||||||
# If true, metadata will be collected with `--all-features`. Note that this can't
|
|
||||||
# be toggled off if true, if you want to conditionally enable `--all-features` it
|
|
||||||
# is recommended to pass `--all-features` on the cmd line instead
|
|
||||||
all-features = true
|
|
||||||
# If true, metadata will be collected with `--no-default-features`. The same
|
|
||||||
# caveat with `all-features` applies
|
|
||||||
no-default-features = false
|
|
||||||
|
|
||||||
# The output table provides options for how/if diagnostics are outputted
|
|
||||||
[output]
|
|
||||||
# When outputting inclusion graphs in diagnostics that include features, this
|
|
||||||
# option can be used to specify the depth at which feature edges will be added.
|
|
||||||
# This option is included since the graphs can be quite large and the addition
|
|
||||||
# of features from the crate(s) to all of the graph roots can be far too verbose.
|
|
||||||
# This option can be overridden via `--feature-depth` on the cmd line
|
|
||||||
feature-depth = 1
|
|
||||||
|
|
||||||
# This section is considered when running `cargo deny check advisories`
|
|
||||||
# More documentation for the advisories section can be found here:
|
|
||||||
# https://embarkstudios.github.io/cargo-deny/checks/advisories/cfg.html
|
|
||||||
[advisories]
|
|
||||||
# A list of advisory IDs to ignore. Note that ignored advisories will still
|
|
||||||
# output a note when they are encountered.
|
|
||||||
ignore = ["RUSTSEC-2024-0370", "RUSTSEC-2024-0436", "RUSTSEC-2023-0089"]
|
|
||||||
# If this is true, then cargo deny will use the git executable to fetch advisory database.
|
|
||||||
# If this is false, then it uses a built-in git library.
|
|
||||||
# Setting this to true can be helpful if you have special authentication requirements that cargo-deny does not support.
|
|
||||||
# See Git Authentication for more information about setting up git authentication.
|
|
||||||
#git-fetch-with-cli = true
|
|
||||||
|
|
||||||
# This section is considered when running `cargo deny check #licenses`
|
|
||||||
# More documentation for the licenses section can be found here:
|
|
||||||
# https://embarkstudios.github.io/cargo-deny/checks/licenses/cfg.html
|
|
||||||
[licenses]
|
|
||||||
# List of explicitly allowed licenses
|
|
||||||
# See https://spdx.org/licenses/ for list of possible licenses
|
|
||||||
# [possible values: any SPDX 3.11 short identifier (+ optional exception)].
|
|
||||||
allow = [
|
|
||||||
"MIT",
|
|
||||||
"Apache-2.0",
|
|
||||||
"Apache-2.0 WITH LLVM-exception",
|
|
||||||
"BSD-3-Clause",
|
|
||||||
"ISC",
|
|
||||||
]
|
|
||||||
# The confidence threshold for detecting a license from license text.
|
|
||||||
# The higher the value, the more closely the license text must be to the
|
|
||||||
# canonical license text of a valid SPDX license file.
|
|
||||||
# [possible values: any between 0.0 and 1.0].
|
|
||||||
confidence-threshold = 0.8
|
|
||||||
# Allow 1 or more licenses on a per-crate basis, so that particular licenses
|
|
||||||
# aren't accepted for every possible crate as with the normal allow list
|
|
||||||
exceptions = [
|
|
||||||
# Each entry is the crate and version constraint, and its specific allow
|
|
||||||
# list
|
|
||||||
{ allow = ["Unicode-DFS-2016", "Unicode-3.0"], crate = "unicode-ident" },
|
|
||||||
{ allow = ["NCSA"], crate = "libfuzzer-sys" },
|
|
||||||
|
|
||||||
]
|
|
||||||
|
|
||||||
[licenses.private]
|
|
||||||
# If true, ignores workspace crates that aren't published, or are only
|
|
||||||
# published to private registries.
|
|
||||||
# To see how to mark a crate as unpublished (to the official registry),
|
|
||||||
# visit https://doc.rust-lang.org/cargo/reference/manifest.html#the-publish-field.
|
|
||||||
ignore = true
|
|
||||||
|
|
||||||
# This section is considered when running `cargo deny check bans`.
|
|
||||||
# More documentation about the 'bans' section can be found here:
|
|
||||||
# https://embarkstudios.github.io/cargo-deny/checks/bans/cfg.html
|
|
||||||
[bans]
|
|
||||||
# Lint level for when multiple versions of the same crate are detected
|
|
||||||
multiple-versions = "warn"
|
|
||||||
# Lint level for when a crate version requirement is `*`
|
|
||||||
wildcards = "allow"
|
|
||||||
# The graph highlighting used when creating dotgraphs for crates
|
|
||||||
# with multiple versions
|
|
||||||
# * lowest-version - The path to the lowest versioned duplicate is highlighted
|
|
||||||
# * simplest-path - The path to the version with the fewest edges is highlighted
|
|
||||||
# * all - Both lowest-version and simplest-path are used
|
|
||||||
highlight = "all"
|
|
||||||
# The default lint level for `default` features for crates that are members of
|
|
||||||
# the workspace that is being checked. This can be overridden by allowing/denying
|
|
||||||
# `default` on a crate-by-crate basis if desired.
|
|
||||||
workspace-default-features = "allow"
|
|
||||||
# The default lint level for `default` features for external crates that are not
|
|
||||||
# members of the workspace. This can be overridden by allowing/denying `default`
|
|
||||||
# on a crate-by-crate basis if desired.
|
|
||||||
external-default-features = "allow"
|
|
||||||
# List of crates that are allowed. Use with care!
|
|
||||||
allow = []
|
|
||||||
# List of crates to deny
|
|
||||||
deny = []
|
|
||||||
|
|
||||||
skip-tree = []
|
|
||||||
|
|
||||||
# This section is considered when running `cargo deny check sources`.
|
|
||||||
# More documentation about the 'sources' section can be found here:
|
|
||||||
# https://embarkstudios.github.io/cargo-deny/checks/sources/cfg.html
|
|
||||||
[sources]
|
|
||||||
# Lint level for what to happen when a crate from a crate registry that is not
|
|
||||||
# in the allow list is encountered
|
|
||||||
unknown-registry = "warn"
|
|
||||||
# Lint level for what to happen when a crate from a git repository that is not
|
|
||||||
# in the allow list is encountered
|
|
||||||
unknown-git = "warn"
|
|
||||||
# List of URLs for allowed crate registries. Defaults to the crates.io index
|
|
||||||
# if not specified. If it is specified but empty, no registries are allowed.
|
|
||||||
allow-registry = ["https://github.com/rust-lang/crates.io-index"]
|
|
||||||
# List of URLs for allowed Git repositories
|
|
||||||
allow-git = ["git+https://github.com/rosenpass/memsec.git?branch=master"]
|
|
||||||
|
|
||||||
[sources.allow-org]
|
|
||||||
# github.com organizations to allow git sources for
|
|
||||||
github = []
|
|
||||||
# gitlab.com organizations to allow git sources for
|
|
||||||
gitlab = []
|
|
||||||
# bitbucket.org organizations to allow git sources for
|
|
||||||
bitbucket = []
|
|
||||||
@@ -1,46 +0,0 @@
|
|||||||
# syntax=docker/dockerfile:1
|
|
||||||
|
|
||||||
ARG BASE_IMAGE=debian:bookworm-slim
|
|
||||||
ARG CHEF_IMAGE=rust:slim-bookworm
|
|
||||||
|
|
||||||
# Stage 1: Base image with cargo-chef installed
|
|
||||||
FROM ${CHEF_IMAGE} AS chef
|
|
||||||
RUN cargo install cargo-chef
|
|
||||||
# install software required for liboqs-rust
|
|
||||||
RUN apt-get update && apt-get install -y clang cmake && rm -rf /var/lib/apt/lists/*
|
|
||||||
|
|
||||||
# Stage 2: Prepare the cargo-chef recipe
|
|
||||||
FROM chef AS planner
|
|
||||||
WORKDIR /app
|
|
||||||
COPY . .
|
|
||||||
RUN cargo chef prepare --recipe-path recipe.json
|
|
||||||
|
|
||||||
# Stage 3: Cache dependencies using the recipe
|
|
||||||
FROM chef AS cacher
|
|
||||||
WORKDIR /app
|
|
||||||
COPY --from=planner /app/recipe.json recipe.json
|
|
||||||
RUN cargo chef cook --release --recipe-path recipe.json
|
|
||||||
|
|
||||||
# Stage 4: Build the application
|
|
||||||
FROM cacher AS builder
|
|
||||||
WORKDIR /app
|
|
||||||
COPY . .
|
|
||||||
RUN cargo build --release
|
|
||||||
|
|
||||||
# Stage 5: Install runtime-dependencies in the base image
|
|
||||||
FROM ${BASE_IMAGE} AS base_image_with_dependencies
|
|
||||||
|
|
||||||
RUN apt-get update && apt-get install -y iproute2 && rm -rf /var/lib/apt/lists/*
|
|
||||||
|
|
||||||
# Final Stage (rosenpass): Copy the rosenpass binary
|
|
||||||
FROM base_image_with_dependencies AS rosenpass
|
|
||||||
COPY --from=builder /app/target/release/rosenpass /usr/local/bin/rosenpass
|
|
||||||
ENTRYPOINT [ "/usr/local/bin/rosenpass" ]
|
|
||||||
|
|
||||||
# Final Stage (rp): Copy the rp binary
|
|
||||||
FROM base_image_with_dependencies AS rp
|
|
||||||
|
|
||||||
RUN apt-get update && apt-get install -y wireguard && rm -rf /var/lib/apt/lists/*
|
|
||||||
|
|
||||||
COPY --from=builder /app/target/release/rp /usr/local/bin/rp
|
|
||||||
ENTRYPOINT [ "/usr/local/bin/rp" ]
|
|
||||||
203
docker/USAGE.md
@@ -1,203 +0,0 @@
|
|||||||
# Rosenpass in Docker
|
|
||||||
|
|
||||||
Rosenpass provides post-quantum-secure key exchange for VPNs. It generates symmetric keys used by [WireGuard](https://www.wireguard.com/papers/wireguard.pdf) or other applications. The protocol enhances "Post-Quantum WireGuard" ([PQWG](https://eprint.iacr.org/2020/379)) with a cookie mechanism for better security against state disruption attacks.
|
|
||||||
|
|
||||||
Prebuilt Docker images are available for easy deployment:
|
|
||||||
|
|
||||||
- [`ghcr.io/rosenpass/rosenpass`](https://github.com/rosenpass/rosenpass/pkgs/container/rosenpass) – the core key exchange tool
|
|
||||||
- [`ghcr.io/rosenpass/rp`](https://github.com/rosenpass/rosenpass/pkgs/container/rp) – a frontend for setting up WireGuard VPNs
|
|
||||||
|
|
||||||
The entrypoint of the `rosenpass` image is the `rosenpass` executable, whose documentation can be found [here](https://rosenpass.eu/docs/rosenpass-tool/manuals/rp_manual/).
|
|
||||||
Similarly, the entrypoint of the `rp` image is the `rp` executable, with its documentation available [here](https://rosenpass.eu/docs/rosenpass-tool/manuals/rp1/).
|
|
||||||
|
|
||||||
## Usage - Standalone Key Exchange
|
|
||||||
|
|
||||||
The `ghcr.io/rosenpass/rosenpass` image can be used in a server-client setup to exchange quantum-secure shared keys.
|
|
||||||
This setup uses rosenpass as a standalone application, without using any other component such as wireguard.
|
|
||||||
What follows, is a simple setup for illustrative purposes.
|
|
||||||
|
|
||||||
Create a docker network that is used to connect the containers:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
docker network create -d bridge rp
|
|
||||||
export NET=rp
|
|
||||||
```
|
|
||||||
|
|
||||||
Generate the server and client key pairs:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
mkdir ./workdir-client ./workdir-server
|
|
||||||
docker run -it --rm -v ./workdir-server:/workdir ghcr.io/rosenpass/rosenpass \
|
|
||||||
gen-keys --public-key=workdir/server-public --secret-key=workdir/server-secret
|
|
||||||
docker run -it --rm -v ./workdir-client:/workdir ghcr.io/rosenpass/rosenpass \
|
|
||||||
gen-keys --public-key=workdir/client-public --secret-key=workdir/client-secret
|
|
||||||
# share the public keys between client and server
|
|
||||||
cp workdir-client/client-public workdir-server/client-public
|
|
||||||
cp workdir-server/server-public workdir-client/server-public
|
|
||||||
```
|
|
||||||
|
|
||||||
Start the server container:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
docker run --name "rpserver" --network ${NET} \
|
|
||||||
-it --rm -v ./workdir-server:/workdir ghcr.io/rosenpass/rosenpass \
|
|
||||||
exchange \
|
|
||||||
private-key workdir/server-secret \
|
|
||||||
public-key workdir/server-public \
|
|
||||||
listen 0.0.0.0:9999 \
|
|
||||||
peer public-key workdir/client-public \
|
|
||||||
outfile workdir/server-sharedkey
|
|
||||||
```
|
|
||||||
|
|
||||||
Find out the ip address of the server container:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
EP="rpserver"
|
|
||||||
EP=$(docker inspect --format '{{ .NetworkSettings.Networks.rp.IPAddress }}' $EP)
|
|
||||||
```
|
|
||||||
|
|
||||||
Run the client container and perform the key exchange:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
docker run --name "rpclient" --network ${NET} \
|
|
||||||
-it --rm -v ./workdir-client:/workdir ghcr.io/rosenpass/rosenpass \
|
|
||||||
exchange \
|
|
||||||
private-key workdir/client-secret \
|
|
||||||
public-key workdir/client-public \
|
|
||||||
peer public-key workdir/server-public endpoint ${EP}:9999 \
|
|
||||||
outfile workdir/client-sharedkey
|
|
||||||
```
|
|
||||||
|
|
||||||
Now the containers will exchange shared keys and each put them into their respective outfile.
|
|
||||||
|
|
||||||
Comparing the outfiles shows that these shared keys equal:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
cmp workdir-server/server-sharedkey workdir-client/client-sharedkey
|
|
||||||
```
|
|
||||||
|
|
||||||
It is now possible to set add these keys as pre-shared keys within a wireguard interface.
|
|
||||||
For example as the server,
|
|
||||||
|
|
||||||
```bash
|
|
||||||
PREKEY=$(cat workdir-server/server-sharedkey)
|
|
||||||
wg set <server-interface> peer <client-peer-public-key> preshared-key <(echo "$PREKEY")
|
|
||||||
```
|
|
||||||
|
|
||||||
## Usage - Combined with wireguard
|
|
||||||
|
|
||||||
The `ghcr.io/rosenpass/rp` image can be used to build a VPN with WireGuard and Rosenpass.
|
|
||||||
In this example, we run two containers on the same system and connect them with a bridge network within the docker overlay network.
|
|
||||||
|
|
||||||
Create the named docker network, to be able to connect the containers.
|
|
||||||
|
|
||||||
Create a docker network that is used to connect the containers:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
docker network create -d bridge rp
|
|
||||||
export NET=rp
|
|
||||||
```
|
|
||||||
|
|
||||||
Generate the server and client secret keys and extract public keys.
|
|
||||||
|
|
||||||
```bash
|
|
||||||
mkdir -p ./workdir-server ./workdir-client
|
|
||||||
|
|
||||||
# server
|
|
||||||
docker run -it --rm -v ./workdir-server:/workdir ghcr.io/rosenpass/rp \
|
|
||||||
genkey workdir/server.rosenpass-secret
|
|
||||||
docker run -it --rm -v ./workdir-server:/workdir ghcr.io/rosenpass/rp \
|
|
||||||
pubkey workdir/server.rosenpass-secret workdir/server.rosenpass-public
|
|
||||||
|
|
||||||
# client
|
|
||||||
docker run -it --rm -v ./workdir-client:/workdir ghcr.io/rosenpass/rp \
|
|
||||||
genkey workdir/client.rosenpass-secret
|
|
||||||
docker run -it --rm -v ./workdir-client:/workdir ghcr.io/rosenpass/rp \
|
|
||||||
pubkey workdir/client.rosenpass-secret workdir/client.rosenpass-public
|
|
||||||
|
|
||||||
# share the public keys between client and server
|
|
||||||
cp -r workdir-client/client.rosenpass-public workdir-server/client.rosenpass-public
|
|
||||||
cp -r workdir-server/server.rosenpass-public workdir-client/server.rosenpass-public
|
|
||||||
```
|
|
||||||
|
|
||||||
Start the server container.
|
|
||||||
Note that the `NET_ADMIN` capability is neccessary, the rp command will create and manage wireguard interfaces.
|
|
||||||
Also make sure the `wireguard` kernel module is loaded by the host. (`lsmod | grep wireguard`)
|
|
||||||
|
|
||||||
```bash
|
|
||||||
docker run --name "rpserver" --network ${NET} -it -d --rm -v ./workdir-server:/workdir \
|
|
||||||
--cap-add=NET_ADMIN \
|
|
||||||
ghcr.io/rosenpass/rp \
|
|
||||||
exchange workdir/server.rosenpass-secret dev rosenpass0 \
|
|
||||||
listen 0.0.0.0:9999 peer workdir/client.rosenpass-public allowed-ips 10.0.0.0/8
|
|
||||||
```
|
|
||||||
|
|
||||||
Now find out the ip-address of the server container and then start the client container:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
EP="rpserver"
|
|
||||||
EP=$(docker inspect --format '{{ .NetworkSettings.Networks.rp.IPAddress }}' $EP)
|
|
||||||
docker run --name "rpclient" --network ${NET} -it -d --rm -v ./workdir-client:/workdir \
|
|
||||||
--cap-add=NET_ADMIN \
|
|
||||||
ghcr.io/rosenpass/rp \
|
|
||||||
exchange workdir/client.rosenpass-secret dev rosenpass1 \
|
|
||||||
peer workdir/server.rosenpass-public endpoint ${EP}:9999 allowed-ips 10.0.0.1
|
|
||||||
```
|
|
||||||
|
|
||||||
Inside the docker containers assign the IP addresses:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# server
|
|
||||||
docker exec -it rpserver ip a add 10.0.0.1/24 dev rosenpass0
|
|
||||||
|
|
||||||
# client
|
|
||||||
docker exec -it rpclient ip a add 10.0.0.2/24 dev rosenpass1
|
|
||||||
```
|
|
||||||
|
|
||||||
Done! The two containers should now be connected through a wireguard VPN (Port 1000) with pre-shared keys exchanged by rosenpass (Port 9999).
|
|
||||||
|
|
||||||
Now, test the connection by starting a shell inside the client container, and ping the server through the VPN:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# client
|
|
||||||
docker exec -it rpclient bash
|
|
||||||
apt update; apt install iputils-ping
|
|
||||||
ping 10.0.0.1
|
|
||||||
```
|
|
||||||
|
|
||||||
The ping command should continuously show ping-logs:
|
|
||||||
|
|
||||||
```
|
|
||||||
PING 10.0.0.1 (10.0.0.1) 56(84) bytes of data.
|
|
||||||
64 bytes from 10.0.0.1: icmp_seq=1 ttl=64 time=0.119 ms
|
|
||||||
64 bytes from 10.0.0.1: icmp_seq=2 ttl=64 time=0.132 ms
|
|
||||||
64 bytes from 10.0.0.1: icmp_seq=3 ttl=64 time=0.394 ms
|
|
||||||
...
|
|
||||||
```
|
|
||||||
|
|
||||||
While the ping is running, you may stop the server container, and verify that the ping-log halts. In another terminal do:
|
|
||||||
|
|
||||||
```
|
|
||||||
docker stop -t 1 rpserver
|
|
||||||
```
|
|
||||||
|
|
||||||
## Building the Docker Images Locally
|
|
||||||
|
|
||||||
Clone the Rosenpass repository:
|
|
||||||
|
|
||||||
```
|
|
||||||
git clone https://github.com/rosenpass/rosenpass
|
|
||||||
cd rosenpass
|
|
||||||
```
|
|
||||||
|
|
||||||
Build the rp image from the root of the repository as follows:
|
|
||||||
|
|
||||||
```
|
|
||||||
docker build -f docker/Dockerfile -t ghcr.io/rosenpass/rp --target rp .
|
|
||||||
```
|
|
||||||
|
|
||||||
Build the rosenpass image from the root of the repostiry with the following command:
|
|
||||||
|
|
||||||
```
|
|
||||||
docker build -f docker/Dockerfile -t ghcr.io/rosenpass/rosenpass --target rosenpass .
|
|
||||||
```
|
|
||||||
212
flake.lock
generated
@@ -1,5 +1,26 @@
|
|||||||
{
|
{
|
||||||
"nodes": {
|
"nodes": {
|
||||||
|
"fenix": {
|
||||||
|
"inputs": {
|
||||||
|
"nixpkgs": [
|
||||||
|
"nixpkgs"
|
||||||
|
],
|
||||||
|
"rust-analyzer-src": "rust-analyzer-src"
|
||||||
|
},
|
||||||
|
"locked": {
|
||||||
|
"lastModified": 1728282832,
|
||||||
|
"narHash": "sha256-I7AbcwGggf+CHqpyd/9PiAjpIBGTGx5woYHqtwxaV7I=",
|
||||||
|
"owner": "nix-community",
|
||||||
|
"repo": "fenix",
|
||||||
|
"rev": "1ec71be1f4b8f3105c5d38da339cb061fefc43f4",
|
||||||
|
"type": "github"
|
||||||
|
},
|
||||||
|
"original": {
|
||||||
|
"owner": "nix-community",
|
||||||
|
"repo": "fenix",
|
||||||
|
"type": "github"
|
||||||
|
}
|
||||||
|
},
|
||||||
"flake-utils": {
|
"flake-utils": {
|
||||||
"inputs": {
|
"inputs": {
|
||||||
"systems": "systems"
|
"systems": "systems"
|
||||||
@@ -18,65 +39,6 @@
|
|||||||
"type": "github"
|
"type": "github"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"flake-utils_2": {
|
|
||||||
"inputs": {
|
|
||||||
"systems": "systems_2"
|
|
||||||
},
|
|
||||||
"locked": {
|
|
||||||
"lastModified": 1726560853,
|
|
||||||
"narHash": "sha256-X6rJYSESBVr3hBoH0WbKE5KvhPU5bloyZ2L4K60/fPQ=",
|
|
||||||
"owner": "numtide",
|
|
||||||
"repo": "flake-utils",
|
|
||||||
"rev": "c1dfcf08411b08f6b8615f7d8971a2bfa81d5e8a",
|
|
||||||
"type": "github"
|
|
||||||
},
|
|
||||||
"original": {
|
|
||||||
"owner": "numtide",
|
|
||||||
"repo": "flake-utils",
|
|
||||||
"type": "github"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"nix-vm-test": {
|
|
||||||
"inputs": {
|
|
||||||
"nixpkgs": [
|
|
||||||
"nixpkgs"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"locked": {
|
|
||||||
"lastModified": 1734355073,
|
|
||||||
"narHash": "sha256-FfdPOGy1zElTwKzjgIMp5K2D3gfPn6VWjVa4MJ9L1Tc=",
|
|
||||||
"owner": "numtide",
|
|
||||||
"repo": "nix-vm-test",
|
|
||||||
"rev": "5948de39a616f2261dbbf4b6f25cbe1cbefd788c",
|
|
||||||
"type": "github"
|
|
||||||
},
|
|
||||||
"original": {
|
|
||||||
"owner": "numtide",
|
|
||||||
"repo": "nix-vm-test",
|
|
||||||
"type": "github"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"nix-vm-test_2": {
|
|
||||||
"inputs": {
|
|
||||||
"nixpkgs": [
|
|
||||||
"rosenpassOld",
|
|
||||||
"nixpkgs"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"locked": {
|
|
||||||
"lastModified": 1734355073,
|
|
||||||
"narHash": "sha256-FfdPOGy1zElTwKzjgIMp5K2D3gfPn6VWjVa4MJ9L1Tc=",
|
|
||||||
"owner": "numtide",
|
|
||||||
"repo": "nix-vm-test",
|
|
||||||
"rev": "5948de39a616f2261dbbf4b6f25cbe1cbefd788c",
|
|
||||||
"type": "github"
|
|
||||||
},
|
|
||||||
"original": {
|
|
||||||
"owner": "numtide",
|
|
||||||
"repo": "nix-vm-test",
|
|
||||||
"type": "github"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"nixpkgs": {
|
"nixpkgs": {
|
||||||
"locked": {
|
"locked": {
|
||||||
"lastModified": 1728193676,
|
"lastModified": 1728193676,
|
||||||
@@ -95,77 +57,25 @@
|
|||||||
},
|
},
|
||||||
"root": {
|
"root": {
|
||||||
"inputs": {
|
"inputs": {
|
||||||
|
"fenix": "fenix",
|
||||||
"flake-utils": "flake-utils",
|
"flake-utils": "flake-utils",
|
||||||
"nix-vm-test": "nix-vm-test",
|
"nixpkgs": "nixpkgs"
|
||||||
"nixpkgs": "nixpkgs",
|
|
||||||
"rosenpassOld": "rosenpassOld",
|
|
||||||
"rust-overlay": "rust-overlay_2",
|
|
||||||
"treefmt-nix": "treefmt-nix_2"
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"rosenpassOld": {
|
"rust-analyzer-src": {
|
||||||
"inputs": {
|
"flake": false,
|
||||||
"flake-utils": "flake-utils_2",
|
|
||||||
"nix-vm-test": "nix-vm-test_2",
|
|
||||||
"nixpkgs": [
|
|
||||||
"nixpkgs"
|
|
||||||
],
|
|
||||||
"rust-overlay": "rust-overlay",
|
|
||||||
"treefmt-nix": "treefmt-nix"
|
|
||||||
},
|
|
||||||
"locked": {
|
"locked": {
|
||||||
"lastModified": 1754748821,
|
"lastModified": 1728249780,
|
||||||
"narHash": "sha256-mMggTZDC97lLvKNOLtDz3GBjjxXFD++e1s0RZsVH/vI=",
|
"narHash": "sha256-J269DvCI5dzBmPrXhAAtj566qt0b22TJtF3TIK+tMsI=",
|
||||||
"owner": "rosenpass",
|
"owner": "rust-lang",
|
||||||
"repo": "rosenpass",
|
"repo": "rust-analyzer",
|
||||||
"rev": "916a9ebb7133f0b22057fb097a473217f261928a",
|
"rev": "2b750da1a1a2c1d2c70896108d7096089842d877",
|
||||||
"type": "github"
|
"type": "github"
|
||||||
},
|
},
|
||||||
"original": {
|
"original": {
|
||||||
"owner": "rosenpass",
|
"owner": "rust-lang",
|
||||||
"repo": "rosenpass",
|
"ref": "nightly",
|
||||||
"rev": "916a9ebb7133f0b22057fb097a473217f261928a",
|
"repo": "rust-analyzer",
|
||||||
"type": "github"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"rust-overlay": {
|
|
||||||
"inputs": {
|
|
||||||
"nixpkgs": [
|
|
||||||
"rosenpassOld",
|
|
||||||
"nixpkgs"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"locked": {
|
|
||||||
"lastModified": 1744513456,
|
|
||||||
"narHash": "sha256-NLVluTmK8d01Iz+WyarQhwFcXpHEwU7m5hH3YQQFJS0=",
|
|
||||||
"owner": "oxalica",
|
|
||||||
"repo": "rust-overlay",
|
|
||||||
"rev": "730fd8e82799219754418483fabe1844262fd1e2",
|
|
||||||
"type": "github"
|
|
||||||
},
|
|
||||||
"original": {
|
|
||||||
"owner": "oxalica",
|
|
||||||
"repo": "rust-overlay",
|
|
||||||
"type": "github"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"rust-overlay_2": {
|
|
||||||
"inputs": {
|
|
||||||
"nixpkgs": [
|
|
||||||
"nixpkgs"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"locked": {
|
|
||||||
"lastModified": 1744513456,
|
|
||||||
"narHash": "sha256-NLVluTmK8d01Iz+WyarQhwFcXpHEwU7m5hH3YQQFJS0=",
|
|
||||||
"owner": "oxalica",
|
|
||||||
"repo": "rust-overlay",
|
|
||||||
"rev": "730fd8e82799219754418483fabe1844262fd1e2",
|
|
||||||
"type": "github"
|
|
||||||
},
|
|
||||||
"original": {
|
|
||||||
"owner": "oxalica",
|
|
||||||
"repo": "rust-overlay",
|
|
||||||
"type": "github"
|
"type": "github"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@@ -183,62 +93,6 @@
|
|||||||
"repo": "default",
|
"repo": "default",
|
||||||
"type": "github"
|
"type": "github"
|
||||||
}
|
}
|
||||||
},
|
|
||||||
"systems_2": {
|
|
||||||
"locked": {
|
|
||||||
"lastModified": 1681028828,
|
|
||||||
"narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=",
|
|
||||||
"owner": "nix-systems",
|
|
||||||
"repo": "default",
|
|
||||||
"rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e",
|
|
||||||
"type": "github"
|
|
||||||
},
|
|
||||||
"original": {
|
|
||||||
"owner": "nix-systems",
|
|
||||||
"repo": "default",
|
|
||||||
"type": "github"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"treefmt-nix": {
|
|
||||||
"inputs": {
|
|
||||||
"nixpkgs": [
|
|
||||||
"rosenpassOld",
|
|
||||||
"nixpkgs"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"locked": {
|
|
||||||
"lastModified": 1743748085,
|
|
||||||
"narHash": "sha256-uhjnlaVTWo5iD3LXics1rp9gaKgDRQj6660+gbUU3cE=",
|
|
||||||
"owner": "numtide",
|
|
||||||
"repo": "treefmt-nix",
|
|
||||||
"rev": "815e4121d6a5d504c0f96e5be2dd7f871e4fd99d",
|
|
||||||
"type": "github"
|
|
||||||
},
|
|
||||||
"original": {
|
|
||||||
"owner": "numtide",
|
|
||||||
"repo": "treefmt-nix",
|
|
||||||
"type": "github"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"treefmt-nix_2": {
|
|
||||||
"inputs": {
|
|
||||||
"nixpkgs": [
|
|
||||||
"nixpkgs"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"locked": {
|
|
||||||
"lastModified": 1743748085,
|
|
||||||
"narHash": "sha256-uhjnlaVTWo5iD3LXics1rp9gaKgDRQj6660+gbUU3cE=",
|
|
||||||
"owner": "numtide",
|
|
||||||
"repo": "treefmt-nix",
|
|
||||||
"rev": "815e4121d6a5d504c0f96e5be2dd7f871e4fd99d",
|
|
||||||
"type": "github"
|
|
||||||
},
|
|
||||||
"original": {
|
|
||||||
"owner": "numtide",
|
|
||||||
"repo": "treefmt-nix",
|
|
||||||
"type": "github"
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"root": "root",
|
"root": "root",
|
||||||
|
|||||||
297
flake.nix
@@ -3,56 +3,37 @@
|
|||||||
nixpkgs.url = "github:NixOS/nixpkgs/nixos-24.05";
|
nixpkgs.url = "github:NixOS/nixpkgs/nixos-24.05";
|
||||||
flake-utils.url = "github:numtide/flake-utils";
|
flake-utils.url = "github:numtide/flake-utils";
|
||||||
|
|
||||||
nix-vm-test.url = "github:numtide/nix-vm-test";
|
|
||||||
nix-vm-test.inputs.nixpkgs.follows = "nixpkgs";
|
|
||||||
nix-vm-test.inputs.flake-utils.follows = "flake-utils";
|
|
||||||
|
|
||||||
# for rust nightly with llvm-tools-preview
|
# for rust nightly with llvm-tools-preview
|
||||||
rust-overlay.url = "github:oxalica/rust-overlay";
|
fenix.url = "github:nix-community/fenix";
|
||||||
rust-overlay.inputs.nixpkgs.follows = "nixpkgs";
|
fenix.inputs.nixpkgs.follows = "nixpkgs";
|
||||||
|
|
||||||
treefmt-nix.url = "github:numtide/treefmt-nix";
|
|
||||||
treefmt-nix.inputs.nixpkgs.follows = "nixpkgs";
|
|
||||||
|
|
||||||
# Older version of rosenpass, referenced here for backwards compatibility
|
|
||||||
rosenpassOld.url = "github:rosenpass/rosenpass?rev=916a9ebb7133f0b22057fb097a473217f261928a";
|
|
||||||
rosenpassOld.inputs.nixpkgs.follows = "nixpkgs";
|
|
||||||
};
|
};
|
||||||
|
|
||||||
outputs =
|
outputs = { self, nixpkgs, flake-utils, ... }@inputs:
|
||||||
{
|
|
||||||
self,
|
|
||||||
nixpkgs,
|
|
||||||
flake-utils,
|
|
||||||
nix-vm-test,
|
|
||||||
rust-overlay,
|
|
||||||
treefmt-nix,
|
|
||||||
rosenpassOld,
|
|
||||||
...
|
|
||||||
}@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 ###
|
### Export the overlay.nix from this flake ###
|
||||||
#
|
#
|
||||||
{ overlays.default = import ./overlay.nix; }
|
{
|
||||||
|
overlays.default = import ./overlay.nix;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
#
|
#
|
||||||
### Actual Rosenpass Package and Docker Container Images ###
|
### Actual Rosenpass Package and Docker Container Images ###
|
||||||
#
|
#
|
||||||
(flake-utils.lib.eachSystem
|
(flake-utils.lib.eachSystem [
|
||||||
[
|
"x86_64-linux"
|
||||||
"x86_64-linux"
|
"aarch64-linux"
|
||||||
"aarch64-linux"
|
|
||||||
|
|
||||||
# unsuported best-effort
|
# unsuported best-effort
|
||||||
"i686-linux"
|
"i686-linux"
|
||||||
"x86_64-darwin"
|
"x86_64-darwin"
|
||||||
"aarch64-darwin"
|
"aarch64-darwin"
|
||||||
# "x86_64-windows"
|
# "x86_64-windows"
|
||||||
]
|
]
|
||||||
(
|
(system:
|
||||||
system:
|
|
||||||
let
|
let
|
||||||
# normal nixpkgs
|
# normal nixpkgs
|
||||||
pkgs = import nixpkgs {
|
pkgs = import nixpkgs {
|
||||||
@@ -63,185 +44,99 @@
|
|||||||
};
|
};
|
||||||
in
|
in
|
||||||
{
|
{
|
||||||
packages =
|
packages = {
|
||||||
{
|
default = pkgs.rosenpass;
|
||||||
default = pkgs.rosenpass;
|
rosenpass = pkgs.rosenpass;
|
||||||
rosenpass = pkgs.rosenpass;
|
rosenpass-oci-image = pkgs.rosenpass-oci-image;
|
||||||
rosenpass-oci-image = pkgs.rosenpass-oci-image;
|
rp = pkgs.rp;
|
||||||
rp = pkgs.rp;
|
|
||||||
|
|
||||||
release-package = pkgs.release-package;
|
release-package = pkgs.release-package;
|
||||||
|
|
||||||
# for good measure, we also offer to cross compile to Linux on Arm
|
# for good measure, we also offer to cross compile to Linux on Arm
|
||||||
aarch64-linux-rosenpass-static = pkgs.pkgsCross.aarch64-multiplatform.pkgsStatic.rosenpass;
|
aarch64-linux-rosenpass-static =
|
||||||
aarch64-linux-rp-static = pkgs.pkgsCross.aarch64-multiplatform.pkgsStatic.rp;
|
pkgs.pkgsCross.aarch64-multiplatform.pkgsStatic.rosenpass;
|
||||||
}
|
aarch64-linux-rp-static = pkgs.pkgsCross.aarch64-multiplatform.pkgsStatic.rp;
|
||||||
//
|
}
|
||||||
# We only offer static builds for linux, as this is not supported on OS X
|
//
|
||||||
(nixpkgs.lib.attrsets.optionalAttrs pkgs.stdenv.isLinux {
|
# We only offer static builds for linux, as this is not supported on OS X
|
||||||
rosenpass-static = pkgs.pkgsStatic.rosenpass;
|
(nixpkgs.lib.attrsets.optionalAttrs pkgs.stdenv.isLinux {
|
||||||
rosenpass-static-oci-image = pkgs.pkgsStatic.rosenpass-oci-image;
|
rosenpass-static = pkgs.pkgsStatic.rosenpass;
|
||||||
rp-static = pkgs.pkgsStatic.rp;
|
rosenpass-static-oci-image = pkgs.pkgsStatic.rosenpass-oci-image;
|
||||||
});
|
rp-static = pkgs.pkgsStatic.rp;
|
||||||
|
});
|
||||||
}
|
}
|
||||||
)
|
))
|
||||||
)
|
|
||||||
|
|
||||||
#
|
#
|
||||||
### Linux specifics ###
|
### Linux specifics ###
|
||||||
#
|
#
|
||||||
(flake-utils.lib.eachSystem
|
(flake-utils.lib.eachSystem [ "x86_64-linux" "aarch64-linux" ] (system:
|
||||||
[
|
let
|
||||||
"x86_64-linux"
|
pkgs = import nixpkgs {
|
||||||
"aarch64-linux"
|
inherit system;
|
||||||
"i686-linux"
|
|
||||||
]
|
|
||||||
(
|
|
||||||
system:
|
|
||||||
let
|
|
||||||
pkgs = import nixpkgs {
|
|
||||||
inherit system;
|
|
||||||
|
|
||||||
overlays = [
|
# apply our own overlay, overriding/inserting our packages as defined in ./pkgs
|
||||||
# apply our own overlay, overriding/inserting our packages as defined in ./pkgs
|
overlays = [ self.overlays.default ];
|
||||||
self.overlays.default
|
};
|
||||||
|
in
|
||||||
|
{
|
||||||
|
|
||||||
nix-vm-test.overlays.default
|
#
|
||||||
|
### Reading materials ###
|
||||||
|
#
|
||||||
|
packages.whitepaper = pkgs.whitepaper;
|
||||||
|
|
||||||
# apply rust-overlay to get specific versions of the rust toolchain for a MSRV check
|
#
|
||||||
(import rust-overlay)
|
### Proof and Proof Tools ###
|
||||||
];
|
#
|
||||||
};
|
packages.proverif-patched = pkgs.proverif-patched;
|
||||||
|
packages.proof-proverif = pkgs.proof-proverif;
|
||||||
|
|
||||||
treefmtEval = treefmt-nix.lib.evalModule pkgs ./treefmt.nix;
|
|
||||||
in
|
|
||||||
{
|
|
||||||
packages.package-deb = pkgs.callPackage ./pkgs/package-deb.nix {
|
|
||||||
rosenpass = pkgs.pkgsStatic.rosenpass;
|
|
||||||
};
|
|
||||||
packages.package-rpm = pkgs.callPackage ./pkgs/package-rpm.nix {
|
|
||||||
rosenpass = pkgs.pkgsStatic.rosenpass;
|
|
||||||
};
|
|
||||||
|
|
||||||
#
|
#
|
||||||
### Reading materials ###
|
### Devshells ###
|
||||||
#
|
#
|
||||||
packages.whitepaper = pkgs.whitepaper;
|
devShells.default = pkgs.mkShell {
|
||||||
|
inherit (pkgs.proof-proverif) CRYPTOVERIF_LIB;
|
||||||
|
inputsFrom = [ pkgs.rosenpass ];
|
||||||
|
nativeBuildInputs = with pkgs; [
|
||||||
|
cargo-release
|
||||||
|
clippy
|
||||||
|
rustfmt
|
||||||
|
nodePackages.prettier
|
||||||
|
nushell # for the .ci/gen-workflow-files.nu script
|
||||||
|
proverif-patched
|
||||||
|
];
|
||||||
|
};
|
||||||
|
devShells.coverage = pkgs.mkShell {
|
||||||
|
inputsFrom = [ pkgs.rosenpass ];
|
||||||
|
nativeBuildInputs = [
|
||||||
|
inputs.fenix.packages.${system}.complete.toolchain
|
||||||
|
pkgs.cargo-llvm-cov
|
||||||
|
];
|
||||||
|
};
|
||||||
|
|
||||||
#
|
|
||||||
### Proof and Proof Tools ###
|
|
||||||
#
|
|
||||||
packages.proverif-patched = pkgs.proverif-patched;
|
|
||||||
packages.proof-proverif = pkgs.proof-proverif;
|
|
||||||
|
|
||||||
#
|
checks = {
|
||||||
### Devshells ###
|
systemd-rosenpass = pkgs.testers.runNixOSTest ./tests/systemd/rosenpass.nix;
|
||||||
#
|
systemd-rp = pkgs.testers.runNixOSTest ./tests/systemd/rp.nix;
|
||||||
devShells.default = pkgs.mkShell {
|
|
||||||
inherit (pkgs.proof-proverif) CRYPTOVERIF_LIB;
|
|
||||||
inputsFrom = [ pkgs.rosenpass ];
|
|
||||||
nativeBuildInputs = with pkgs; [
|
|
||||||
cargo-release
|
|
||||||
clippy
|
|
||||||
rustfmt
|
|
||||||
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-audit
|
|
||||||
cargo-msrv
|
|
||||||
cargo-release
|
|
||||||
cargo-vet
|
|
||||||
rustfmt
|
|
||||||
nodePackages.prettier
|
|
||||||
nushell # for the .ci/gen-workflow-files.nu script
|
|
||||||
proverif-patched
|
|
||||||
pkgs.cargo-llvm-cov
|
|
||||||
pkgs.grcov
|
|
||||||
pkgs.rust-bin.stable.latest.complete
|
|
||||||
];
|
|
||||||
};
|
|
||||||
devShells.coverage = pkgs.mkShell {
|
|
||||||
inputsFrom = [ pkgs.rosenpass ];
|
|
||||||
nativeBuildInputs = [
|
|
||||||
pkgs.cargo-llvm-cov
|
|
||||||
pkgs.grcov
|
|
||||||
pkgs.rustc.llvmPackages.llvm
|
|
||||||
];
|
|
||||||
env = {
|
|
||||||
inherit (pkgs.cargo-llvm-cov) LLVM_COV LLVM_PROFDATA;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
devShells.benchmarks = pkgs.mkShell {
|
|
||||||
inputsFrom = [ pkgs.rosenpass ];
|
|
||||||
nativeBuildInputs = with pkgs; [
|
|
||||||
cargo-release
|
|
||||||
clippy
|
|
||||||
rustfmt
|
|
||||||
];
|
|
||||||
};
|
|
||||||
# a devshell to hunt unsafe `unsafe` in the code
|
|
||||||
devShells.miri = pkgs.mkShell {
|
|
||||||
# inputsFrom = [ self.packages.${system}.rosenpass ];
|
|
||||||
nativeBuildInputs = with pkgs; [
|
|
||||||
((rust-bin.selectLatestNightlyWith (toolchain: toolchain.default)).override {
|
|
||||||
extensions = [
|
|
||||||
"rust-analysis"
|
|
||||||
"rust-src"
|
|
||||||
"miri-preview"
|
|
||||||
];
|
|
||||||
})
|
|
||||||
pkgs.cmake
|
|
||||||
pkgs.rustPlatform.bindgenHook
|
|
||||||
];
|
|
||||||
# Run this to find unsafe `unsafe`:
|
|
||||||
# MIRIFLAGS="-Zmiri-disable-isolation" cargo miri test --no-fail-fast --lib --bins --tests
|
|
||||||
#
|
|
||||||
# - Some test failure is expected.
|
|
||||||
};
|
|
||||||
|
|
||||||
checks =
|
cargo-fmt = pkgs.runCommand "check-cargo-fmt"
|
||||||
import ./tests/integration/integration-checks.nix {
|
{ inherit (self.devShells.${system}.default) nativeBuildInputs buildInputs; } ''
|
||||||
inherit system;
|
cargo fmt --manifest-path=${./.}/Cargo.toml --check --all && touch $out
|
||||||
pkgs = inputs.nixpkgs;
|
'';
|
||||||
lib = nixpkgs.lib;
|
nixpkgs-fmt = pkgs.runCommand "check-nixpkgs-fmt"
|
||||||
rosenpassNew = self.packages.${system}.default;
|
{ nativeBuildInputs = [ pkgs.nixpkgs-fmt ]; } ''
|
||||||
rosenpassOld = rosenpassOld.packages.${system}.default;
|
nixpkgs-fmt --check ${./.} && touch $out
|
||||||
}
|
'';
|
||||||
// {
|
prettier-check = pkgs.runCommand "check-with-prettier"
|
||||||
systemd-rosenpass = pkgs.testers.runNixOSTest ./tests/systemd/rosenpass.nix;
|
{ nativeBuildInputs = [ pkgs.nodePackages.prettier ]; } ''
|
||||||
systemd-rp = pkgs.testers.runNixOSTest ./tests/systemd/rp.nix;
|
cd ${./.} && prettier --check . && touch $out
|
||||||
formatting = treefmtEval.config.build.check self;
|
'';
|
||||||
rosenpass-msrv-check =
|
};
|
||||||
let
|
|
||||||
rosenpassCargoToml = pkgs.lib.trivial.importTOML ./rosenpass/Cargo.toml;
|
|
||||||
|
|
||||||
rustToolchain = pkgs.rust-bin.stable.${rosenpassCargoToml.package.rust-version}.default;
|
formatter = pkgs.nixpkgs-fmt;
|
||||||
rustPlatform = pkgs.makeRustPlatform {
|
}))
|
||||||
cargo = rustToolchain;
|
|
||||||
rustc = rustToolchain;
|
|
||||||
};
|
|
||||||
in
|
|
||||||
pkgs.rosenpass.override { inherit rustPlatform; };
|
|
||||||
}
|
|
||||||
// pkgs.lib.optionalAttrs (system == "x86_64-linux") (
|
|
||||||
import ./tests/legacy-distro-packaging.nix {
|
|
||||||
inherit pkgs;
|
|
||||||
rosenpass-deb = self.packages.${system}.package-deb;
|
|
||||||
rosenpass-rpm = self.packages.${system}.package-rpm;
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
# for `nix fmt`
|
|
||||||
formatter = treefmtEval.config.build.wrapper;
|
|
||||||
}
|
|
||||||
)
|
|
||||||
)
|
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,10 +3,9 @@ name = "rosenpass-fuzzing"
|
|||||||
version = "0.0.1"
|
version = "0.0.1"
|
||||||
publish = false
|
publish = false
|
||||||
edition = "2021"
|
edition = "2021"
|
||||||
rust-version = "1.77.0"
|
|
||||||
|
|
||||||
[features]
|
[features]
|
||||||
experiment_libcrux = ["rosenpass-ciphers/experiment_libcrux_all"]
|
experiment_libcrux = ["rosenpass-ciphers/experiment_libcrux"]
|
||||||
|
|
||||||
[package.metadata]
|
[package.metadata]
|
||||||
cargo-fuzz = true
|
cargo-fuzz = true
|
||||||
|
|||||||
@@ -4,8 +4,7 @@ extern crate rosenpass;
|
|||||||
|
|
||||||
use libfuzzer_sys::fuzz_target;
|
use libfuzzer_sys::fuzz_target;
|
||||||
|
|
||||||
use rosenpass_cipher_traits::primitives::Aead as _;
|
use rosenpass_ciphers::aead;
|
||||||
use rosenpass_ciphers::Aead;
|
|
||||||
|
|
||||||
#[derive(arbitrary::Arbitrary, Debug)]
|
#[derive(arbitrary::Arbitrary, Debug)]
|
||||||
pub struct Input {
|
pub struct Input {
|
||||||
@@ -18,7 +17,7 @@ pub struct Input {
|
|||||||
fuzz_target!(|input: Input| {
|
fuzz_target!(|input: Input| {
|
||||||
let mut ciphertext = vec![0u8; input.plaintext.len() + 16];
|
let mut ciphertext = vec![0u8; input.plaintext.len() + 16];
|
||||||
|
|
||||||
Aead.encrypt(
|
aead::encrypt(
|
||||||
ciphertext.as_mut_slice(),
|
ciphertext.as_mut_slice(),
|
||||||
&input.key,
|
&input.key,
|
||||||
&input.nonce,
|
&input.nonce,
|
||||||
|
|||||||
@@ -4,7 +4,6 @@ extern crate rosenpass;
|
|||||||
|
|
||||||
use libfuzzer_sys::fuzz_target;
|
use libfuzzer_sys::fuzz_target;
|
||||||
|
|
||||||
use rosenpass_cipher_traits::primitives::KeyedHashTo;
|
|
||||||
use rosenpass_ciphers::subtle::blake2b;
|
use rosenpass_ciphers::subtle::blake2b;
|
||||||
use rosenpass_to::To;
|
use rosenpass_to::To;
|
||||||
|
|
||||||
@@ -17,7 +16,5 @@ pub struct Blake2b {
|
|||||||
fuzz_target!(|input: Blake2b| {
|
fuzz_target!(|input: Blake2b| {
|
||||||
let mut out = [0u8; 32];
|
let mut out = [0u8; 32];
|
||||||
|
|
||||||
blake2b::Blake2b::keyed_hash_to(&input.key, &input.data)
|
blake2b::hash(&input.key, &input.data).to(&mut out).unwrap();
|
||||||
.to(&mut out)
|
|
||||||
.unwrap();
|
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -4,8 +4,8 @@ extern crate rosenpass;
|
|||||||
use libfuzzer_sys::fuzz_target;
|
use libfuzzer_sys::fuzz_target;
|
||||||
|
|
||||||
use rosenpass::protocol::CryptoServer;
|
use rosenpass::protocol::CryptoServer;
|
||||||
use rosenpass_cipher_traits::primitives::Kem;
|
use rosenpass_cipher_traits::Kem;
|
||||||
use rosenpass_ciphers::StaticKem;
|
use rosenpass_ciphers::kem::StaticKem;
|
||||||
use rosenpass_secret_memory::policy::*;
|
use rosenpass_secret_memory::policy::*;
|
||||||
use rosenpass_secret_memory::{PublicBox, Secret};
|
use rosenpass_secret_memory::{PublicBox, Secret};
|
||||||
use std::sync::Once;
|
use std::sync::Once;
|
||||||
|
|||||||
@@ -4,8 +4,8 @@ extern crate rosenpass;
|
|||||||
|
|
||||||
use libfuzzer_sys::fuzz_target;
|
use libfuzzer_sys::fuzz_target;
|
||||||
|
|
||||||
use rosenpass_cipher_traits::primitives::Kem;
|
use rosenpass_cipher_traits::Kem;
|
||||||
use rosenpass_ciphers::EphemeralKem;
|
use rosenpass_ciphers::kem::EphemeralKem;
|
||||||
|
|
||||||
#[derive(arbitrary::Arbitrary, Debug)]
|
#[derive(arbitrary::Arbitrary, Debug)]
|
||||||
pub struct Input {
|
pub struct Input {
|
||||||
@@ -16,7 +16,5 @@ fuzz_target!(|input: Input| {
|
|||||||
let mut ciphertext = [0u8; EphemeralKem::CT_LEN];
|
let mut ciphertext = [0u8; EphemeralKem::CT_LEN];
|
||||||
let mut shared_secret = [0u8; EphemeralKem::SHK_LEN];
|
let mut shared_secret = [0u8; EphemeralKem::SHK_LEN];
|
||||||
|
|
||||||
EphemeralKem
|
EphemeralKem::encaps(&mut shared_secret, &mut ciphertext, &input.pk).unwrap();
|
||||||
.encaps(&mut shared_secret, &mut ciphertext, &input.pk)
|
|
||||||
.unwrap();
|
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -3,13 +3,13 @@ extern crate rosenpass;
|
|||||||
|
|
||||||
use libfuzzer_sys::fuzz_target;
|
use libfuzzer_sys::fuzz_target;
|
||||||
|
|
||||||
use rosenpass_cipher_traits::primitives::Kem;
|
use rosenpass_cipher_traits::Kem;
|
||||||
use rosenpass_ciphers::StaticKem;
|
use rosenpass_ciphers::kem::StaticKem;
|
||||||
|
|
||||||
fuzz_target!(|input: [u8; StaticKem::PK_LEN]| {
|
fuzz_target!(|input: [u8; StaticKem::PK_LEN]| {
|
||||||
let mut ciphertext = [0u8; StaticKem::CT_LEN];
|
let mut ciphertext = [0u8; StaticKem::CT_LEN];
|
||||||
let mut shared_secret = [0u8; StaticKem::SHK_LEN];
|
let mut shared_secret = [0u8; StaticKem::SHK_LEN];
|
||||||
|
|
||||||
// We expect errors while fuzzing therefore we do not check the result.
|
// We expect errors while fuzzing therefore we do not check the result.
|
||||||
let _ = StaticKem.encaps(&mut shared_secret, &mut ciphertext, &input);
|
let _ = StaticKem::encaps(&mut shared_secret, &mut ciphertext, &input);
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -8,7 +8,6 @@ description = "Rosenpass internal bindings to liboqs"
|
|||||||
homepage = "https://rosenpass.eu/"
|
homepage = "https://rosenpass.eu/"
|
||||||
repository = "https://github.com/rosenpass/rosenpass"
|
repository = "https://github.com/rosenpass/rosenpass"
|
||||||
readme = "readme.md"
|
readme = "readme.md"
|
||||||
rust-version = "1.77.0"
|
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
rosenpass-cipher-traits = { workspace = true }
|
rosenpass-cipher-traits = { workspace = true }
|
||||||
|
|||||||
@@ -2,10 +2,11 @@
|
|||||||
|
|
||||||
/// Generate bindings to a liboqs-provided KEM
|
/// Generate bindings to a liboqs-provided KEM
|
||||||
macro_rules! oqs_kem {
|
macro_rules! oqs_kem {
|
||||||
($name:ident, $algo_trait:path) => { ::paste::paste!{
|
($name:ident) => { ::paste::paste!{
|
||||||
#[doc = "Bindings for ::oqs_sys::kem::" [<"OQS_KEM" _ $name:snake>] "_*"]
|
#[doc = "Bindings for ::oqs_sys::kem::" [<"OQS_KEM" _ $name:snake>] "_*"]
|
||||||
mod [< $name:snake >] {
|
mod [< $name:snake >] {
|
||||||
use rosenpass_cipher_traits::primitives::{Kem, KemError};
|
use rosenpass_cipher_traits::Kem;
|
||||||
|
use rosenpass_util::result::Guaranteed;
|
||||||
|
|
||||||
#[doc = "Bindings for ::oqs_sys::kem::" [<"OQS_KEM" _ $name:snake>] "_*"]
|
#[doc = "Bindings for ::oqs_sys::kem::" [<"OQS_KEM" _ $name:snake>] "_*"]
|
||||||
#[doc = ""]
|
#[doc = ""]
|
||||||
@@ -13,7 +14,7 @@ macro_rules! oqs_kem {
|
|||||||
#[doc = ""]
|
#[doc = ""]
|
||||||
#[doc = "```rust"]
|
#[doc = "```rust"]
|
||||||
#[doc = "use std::borrow::{Borrow, BorrowMut};"]
|
#[doc = "use std::borrow::{Borrow, BorrowMut};"]
|
||||||
#[doc = "use rosenpass_cipher_traits::primitives::Kem;"]
|
#[doc = "use rosenpass_cipher_traits::Kem;"]
|
||||||
#[doc = "use rosenpass_oqs::" $name:camel " as MyKem;"]
|
#[doc = "use rosenpass_oqs::" $name:camel " as MyKem;"]
|
||||||
#[doc = "use rosenpass_secret_memory::{Secret, Public};"]
|
#[doc = "use rosenpass_secret_memory::{Secret, Public};"]
|
||||||
#[doc = ""]
|
#[doc = ""]
|
||||||
@@ -22,26 +23,21 @@ macro_rules! oqs_kem {
|
|||||||
#[doc = "// Recipient generates secret key, transfers pk to sender"]
|
#[doc = "// Recipient generates secret key, transfers pk to sender"]
|
||||||
#[doc = "let mut sk = Secret::<{ MyKem::SK_LEN }>::zero();"]
|
#[doc = "let mut sk = Secret::<{ MyKem::SK_LEN }>::zero();"]
|
||||||
#[doc = "let mut pk = Public::<{ MyKem::PK_LEN }>::zero();"]
|
#[doc = "let mut pk = Public::<{ MyKem::PK_LEN }>::zero();"]
|
||||||
#[doc = "MyKem.keygen(sk.secret_mut(), &mut pk);"]
|
#[doc = "MyKem::keygen(sk.secret_mut(), pk.borrow_mut());"]
|
||||||
#[doc = ""]
|
#[doc = ""]
|
||||||
#[doc = "// Sender generates ciphertext and local shared key, sends ciphertext to recipient"]
|
#[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 shk_enc = Secret::<{ MyKem::SHK_LEN }>::zero();"]
|
||||||
#[doc = "let mut ct = Public::<{ MyKem::CT_LEN }>::zero();"]
|
#[doc = "let mut ct = Public::<{ MyKem::CT_LEN }>::zero();"]
|
||||||
#[doc = "MyKem.encaps(shk_enc.secret_mut(), &mut ct, &pk);"]
|
#[doc = "MyKem::encaps(shk_enc.secret_mut(), ct.borrow_mut(), pk.borrow());"]
|
||||||
#[doc = ""]
|
#[doc = ""]
|
||||||
#[doc = "// Recipient decapsulates ciphertext"]
|
#[doc = "// Recipient decapsulates ciphertext"]
|
||||||
#[doc = "let mut shk_dec = Secret::<{ MyKem::SHK_LEN }>::zero();"]
|
#[doc = "let mut shk_dec = Secret::<{ MyKem::SHK_LEN }>::zero();"]
|
||||||
#[doc = "MyKem.decaps(shk_dec.secret_mut(), sk.secret_mut(), &ct);"]
|
#[doc = "MyKem::decaps(shk_dec.secret_mut(), sk.secret(), ct.borrow());"]
|
||||||
#[doc = ""]
|
#[doc = ""]
|
||||||
#[doc = "// Both parties end up with the same shared key"]
|
#[doc = "// Both parties end up with the same shared key"]
|
||||||
#[doc = "assert!(rosenpass_constant_time::compare(shk_enc.secret(), shk_dec.secret()) == 0);"]
|
#[doc = "assert!(rosenpass_constant_time::compare(shk_enc.secret_mut(), shk_dec.secret_mut()) == 0);"]
|
||||||
#[doc = "```"]
|
#[doc = "```"]
|
||||||
pub struct [< $name:camel >];
|
pub enum [< $name:camel >] {}
|
||||||
|
|
||||||
pub const SK_LEN: usize = ::oqs_sys::kem::[<OQS_KEM _ $name:snake _ length_secret_key >] as usize;
|
|
||||||
pub const PK_LEN: usize = ::oqs_sys::kem::[<OQS_KEM _ $name:snake _ length_public_key >] as usize;
|
|
||||||
pub const CT_LEN: usize = ::oqs_sys::kem::[<OQS_KEM _ $name:snake _ length_ciphertext >] as usize;
|
|
||||||
pub const SHK_LEN: usize = ::oqs_sys::kem::[<OQS_KEM _ $name:snake _ length_shared_secret >] as usize;
|
|
||||||
|
|
||||||
/// # Panic & Safety
|
/// # Panic & Safety
|
||||||
///
|
///
|
||||||
@@ -55,8 +51,17 @@ macro_rules! oqs_kem {
|
|||||||
/// to only check that the buffers are big enough, allowing them to be even
|
/// 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
|
/// bigger. However, from a correctness point of view it does not make sense to
|
||||||
/// allow bigger buffers.
|
/// allow bigger buffers.
|
||||||
impl Kem<SK_LEN, PK_LEN, CT_LEN, SHK_LEN> for [< $name:camel >] {
|
impl Kem for [< $name:camel >] {
|
||||||
fn keygen(&self, sk: &mut [u8; SK_LEN], pk: &mut [u8; PK_LEN]) -> Result<(), KemError> {
|
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 {
|
unsafe {
|
||||||
oqs_call!(
|
oqs_call!(
|
||||||
::oqs_sys::kem::[< OQS_KEM _ $name:snake _ keypair >],
|
::oqs_sys::kem::[< OQS_KEM _ $name:snake _ keypair >],
|
||||||
@@ -68,7 +73,10 @@ macro_rules! oqs_kem {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn encaps(&self, shk: &mut [u8; SHK_LEN], ct: &mut [u8; CT_LEN], pk: &[u8; PK_LEN]) -> Result<(), KemError> {
|
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 {
|
unsafe {
|
||||||
oqs_call!(
|
oqs_call!(
|
||||||
::oqs_sys::kem::[< OQS_KEM _ $name:snake _ encaps >],
|
::oqs_sys::kem::[< OQS_KEM _ $name:snake _ encaps >],
|
||||||
@@ -81,7 +89,10 @@ macro_rules! oqs_kem {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn decaps(&self, shk: &mut [u8; SHK_LEN], sk: &[u8; SK_LEN], ct: &[u8; CT_LEN]) -> Result<(), KemError> {
|
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 {
|
unsafe {
|
||||||
oqs_call!(
|
oqs_call!(
|
||||||
::oqs_sys::kem::[< OQS_KEM _ $name:snake _ decaps >],
|
::oqs_sys::kem::[< OQS_KEM _ $name:snake _ decaps >],
|
||||||
@@ -94,16 +105,9 @@ macro_rules! oqs_kem {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
impl Default for [< $name:camel >] {
|
|
||||||
fn default() -> Self {
|
|
||||||
Self
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl $algo_trait for [< $name:camel >] {}
|
|
||||||
|
|
||||||
pub use [< $name:snake >] :: [< $name:camel >];
|
pub use [< $name:snake >] :: [< $name:camel >];
|
||||||
}}
|
}}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -22,8 +22,5 @@ macro_rules! oqs_call {
|
|||||||
|
|
||||||
#[macro_use]
|
#[macro_use]
|
||||||
mod kem_macro;
|
mod kem_macro;
|
||||||
oqs_kem!(kyber_512, rosenpass_cipher_traits::algorithms::KemKyber512);
|
oqs_kem!(kyber_512);
|
||||||
oqs_kem!(
|
oqs_kem!(classic_mceliece_460896);
|
||||||
classic_mceliece_460896,
|
|
||||||
rosenpass_cipher_traits::algorithms::KemClassicMceliece460896
|
|
||||||
);
|
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
final: prev: {
|
final: prev: {
|
||||||
|
|
||||||
|
|
||||||
#
|
#
|
||||||
### Actual rosenpass software ###
|
### Actual rosenpass software ###
|
||||||
#
|
#
|
||||||
@@ -26,10 +27,7 @@ final: prev: {
|
|||||||
"marzipan(/marzipan.awk)?"
|
"marzipan(/marzipan.awk)?"
|
||||||
"analysis(/.*)?"
|
"analysis(/.*)?"
|
||||||
];
|
];
|
||||||
nativeBuildInputs = [
|
nativeBuildInputs = [ final.proverif final.graphviz ];
|
||||||
final.proverif
|
|
||||||
final.graphviz
|
|
||||||
];
|
|
||||||
CRYPTOVERIF_LIB = final.proverif-patched + "/lib/cryptoverif.pvl";
|
CRYPTOVERIF_LIB = final.proverif-patched + "/lib/cryptoverif.pvl";
|
||||||
installPhase = ''
|
installPhase = ''
|
||||||
mkdir -p $out
|
mkdir -p $out
|
||||||
|
|||||||
BIN
papers/graphics/rosenpass-wp-hashing-tree-rgb.pdf
Normal file
2341
papers/graphics/rosenpass-wp-hashing-tree-rgb.svg
Normal file
|
After Width: | Height: | Size: 201 KiB |
|
Before Width: | Height: | Size: 751 KiB After Width: | Height: | Size: 725 KiB |
|
Before Width: | Height: | Size: 221 KiB After Width: | Height: | Size: 218 KiB |
BIN
papers/graphics/rosenpass-wp-key-exchange-protocol-rgb.pdf
Normal file
191
papers/graphics/rosenpass-wp-key-exchange-protocol-rgb.svg
Normal file
@@ -0,0 +1,191 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||||
|
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
|
||||||
|
<svg width="100%" height="100%" viewBox="0 0 2037 1491" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xml:space="preserve" xmlns:serif="http://www.serif.com/" style="fill-rule:evenodd;clip-rule:evenodd;stroke-linejoin:round;stroke-miterlimit:1.5;">
|
||||||
|
<g transform="matrix(0.958104,0,0,0.883458,-169.743,-156.518)">
|
||||||
|
<rect id="ArtBoard1" x="177.165" y="177.165" width="2125.98" height="1687.51" style="fill:none;"/>
|
||||||
|
<clipPath id="_clip1">
|
||||||
|
<rect id="ArtBoard11" serif:id="ArtBoard1" x="177.165" y="177.165" width="2125.98" height="1687.51"/>
|
||||||
|
</clipPath>
|
||||||
|
<g clip-path="url(#_clip1)">
|
||||||
|
<g transform="matrix(0.377816,0,0,0.318513,-62.5845,3.62207)">
|
||||||
|
<path d="M1608.99,599.153C1608.99,575.987 1594.37,557.179 1576.37,557.179L680.292,557.179C662.284,557.179 647.664,575.987 647.664,599.153L647.664,903.661C647.664,926.827 662.284,945.635 680.292,945.635L1576.37,945.635C1594.37,945.635 1608.99,926.827 1608.99,903.661L1608.99,599.153Z" style="fill:rgb(247,4,132);"/>
|
||||||
|
</g>
|
||||||
|
<g transform="matrix(1.11885,0,0,0.472336,1334.4,22.5297)">
|
||||||
|
<path d="M497.076,394.18L497.076,1793.56C497.076,1793.56 -810.094,1791.78 -810.094,1793.56L-810.094,2231.73L497.076,2231.73L497.076,3888.59" style="fill:none;stroke:rgb(255,166,48);stroke-width:15.37px;"/>
|
||||||
|
</g>
|
||||||
|
<g transform="matrix(1.10326,0,0,0.239529,-152.083,336.057)">
|
||||||
|
<g transform="matrix(0.946041,-0,-0,4.72559,298.433,-663.352)">
|
||||||
|
<path d="M1597.09,252.781L1609.59,265.281L1597.09,277.781" style="fill:none;stroke:rgb(247,4,132);stroke-width:8.33px;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:10;"/>
|
||||||
|
<path d="M209.973,265.281L1609.59,265.281" style="fill:none;stroke:rgb(247,4,132);stroke-width:8.33px;stroke-linecap:round;stroke-dasharray:8.33,16.67,0,0;"/>
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
<g transform="matrix(0.54423,0,0,0.514519,523.603,90.8277)">
|
||||||
|
<path d="M1608.99,583.163C1608.99,568.822 1598.85,557.179 1586.34,557.179L670.315,557.179C657.814,557.179 647.664,568.822 647.664,583.163L647.664,919.651C647.664,933.992 657.814,945.635 670.315,945.635L1586.34,945.635C1598.85,945.635 1608.99,933.992 1608.99,919.651L1608.99,583.163Z" style="fill:rgb(247,4,132);"/>
|
||||||
|
<path d="M1624.98,583.163L1624.98,919.651C1624.98,944.11 1607.66,963.968 1586.34,963.968L670.315,963.968C648.993,963.968 631.682,944.11 631.682,919.651L631.682,583.163C631.682,558.704 648.993,538.846 670.315,538.846L1586.34,538.846C1607.66,538.846 1624.98,558.704 1624.98,583.163ZM1608.99,583.163C1608.99,568.822 1598.85,557.179 1586.34,557.179L670.315,557.179C657.814,557.179 647.664,568.822 647.664,583.163L647.664,919.651C647.664,933.992 657.814,945.635 670.315,945.635L1586.34,945.635C1598.85,945.635 1608.99,933.992 1608.99,919.651L1608.99,583.163Z" style="fill:white;"/>
|
||||||
|
</g>
|
||||||
|
<g transform="matrix(1.04373,0,0,1.13192,-323.596,-1172.27)">
|
||||||
|
<g transform="matrix(50,0,0,50,1497.15,1475.25)">
|
||||||
|
</g>
|
||||||
|
<text x="1302.95px" y="1475.25px" style="font-family:'Nunito-Medium', 'Nunito';font-weight:500;font-size:50px;">InitHell<tspan x="1469.15px " y="1475.25px ">o</tspan></text>
|
||||||
|
</g>
|
||||||
|
<g transform="matrix(1.10157,0,0,0.239529,-151.245,1006.25)">
|
||||||
|
<g transform="matrix(0.947489,-0,-0,4.72559,298.129,-3461.31)">
|
||||||
|
<path d="M1597.09,844.867L1609.59,857.367L1597.09,869.867" style="fill:none;stroke:rgb(247,4,132);stroke-width:8.33px;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:10;"/>
|
||||||
|
<path d="M209.973,857.367L1609.59,857.367" style="fill:none;stroke:rgb(247,4,132);stroke-width:8.33px;stroke-linecap:round;stroke-dasharray:8.33,16.67,0,0;"/>
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
<g transform="matrix(0.54423,0,0,0.514519,523.603,752.344)">
|
||||||
|
<path d="M1608.99,583.163C1608.99,568.822 1598.85,557.179 1586.34,557.179L670.315,557.179C657.814,557.179 647.664,568.822 647.664,583.163L647.664,919.651C647.664,933.992 657.814,945.635 670.315,945.635L1586.34,945.635C1598.85,945.635 1608.99,933.992 1608.99,919.651L1608.99,583.163Z" style="fill:rgb(247,4,132);"/>
|
||||||
|
<path d="M1624.98,583.163L1624.98,919.651C1624.98,944.11 1607.66,963.968 1586.34,963.968L670.315,963.968C648.993,963.968 631.682,944.11 631.682,919.651L631.682,583.163C631.682,558.704 648.993,538.846 670.315,538.846L1586.34,538.846C1607.66,538.846 1624.98,558.704 1624.98,583.163ZM1608.99,583.163C1608.99,568.822 1598.85,557.179 1586.34,557.179L670.315,557.179C657.814,557.179 647.664,568.822 647.664,583.163L647.664,919.651C647.664,933.992 657.814,945.635 670.315,945.635L1586.34,945.635C1598.85,945.635 1608.99,933.992 1608.99,919.651L1608.99,583.163Z" style="fill:white;"/>
|
||||||
|
</g>
|
||||||
|
<g transform="matrix(0.19416,0,0,0.275328,1052.99,940.806)">
|
||||||
|
<path d="M1608.99,571.746C1608.99,563.706 1600.46,557.179 1589.95,557.179L666.712,557.179C656.199,557.179 647.664,563.706 647.664,571.746L647.664,931.068C647.664,939.108 656.199,945.635 666.712,945.635L1589.95,945.635C1600.46,945.635 1608.99,939.108 1608.99,931.068L1608.99,571.746Z" style="fill:rgb(255,211,152);stroke:white;stroke-width:19.24px;stroke-linecap:round;"/>
|
||||||
|
</g>
|
||||||
|
<g transform="matrix(1.04373,0,0,1.13192,-345.04,-502.074)">
|
||||||
|
<g transform="matrix(50,0,0,50,1404.28,1475.25)">
|
||||||
|
</g>
|
||||||
|
<text x="1227.23px" y="1475.25px" style="font-family:'Nunito-Medium', 'Nunito';font-weight:500;font-size:50px;">InitC<tspan x="1330.68px " y="1475.25px ">o</tspan>nf</text>
|
||||||
|
</g>
|
||||||
|
<g transform="matrix(1.04373,0,0,1.13192,-34.3588,-501.229)">
|
||||||
|
<g transform="matrix(41.6667,0,0,41.6667,1315.29,1464.53)">
|
||||||
|
</g>
|
||||||
|
<text x="1188.09px" y="1464.53px" style="font-family:'Nunito-SemiBold', 'Nunito';font-weight:600;font-size:41.667px;">Biscuit</text>
|
||||||
|
</g>
|
||||||
|
<g transform="matrix(8.61155e-18,1.13192,-0.0754413,3.71795e-17,1069.8,-342.031)">
|
||||||
|
<path d="M497.076,394.18L497.076,1793.56" style="fill:none;stroke:rgb(247,4,132);stroke-width:17.63px;"/>
|
||||||
|
</g>
|
||||||
|
<g transform="matrix(8.61155e-18,1.13192,-0.0754413,3.71795e-17,1069.8,-288.169)">
|
||||||
|
<path d="M497.076,394.18L497.076,1793.56" style="fill:none;stroke:rgb(255,166,48);stroke-width:17.63px;"/>
|
||||||
|
</g>
|
||||||
|
<g transform="matrix(1.10808,0,0,1.04133,-187.35,-115.819)">
|
||||||
|
<path d="M497.076,394.18L497.076,1896.68" style="fill:none;stroke:rgb(247,4,132);stroke-width:12.58px;"/>
|
||||||
|
</g>
|
||||||
|
<g transform="matrix(-1.09658,0,0,0.321304,2399.88,618.547)">
|
||||||
|
<g transform="matrix(-0.9518,0,0,3.52288,2026.95,-1373.72)">
|
||||||
|
<path d="M220.225,569.992L207.725,557.492L220.225,544.992" style="fill:none;stroke:rgb(255,166,48);stroke-width:8.33px;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:10;"/>
|
||||||
|
<path d="M1607.34,557.492L207.725,557.492" style="fill:none;stroke:rgb(255,166,48);stroke-width:8.33px;stroke-linecap:round;stroke-dasharray:8.33,16.67,0,0;"/>
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
<g transform="matrix(0.54423,0,0,0.514519,523.603,421.586)">
|
||||||
|
<path d="M1608.99,583.163C1608.99,568.822 1598.85,557.179 1586.34,557.179L670.315,557.179C657.814,557.179 647.664,568.822 647.664,583.163L647.664,919.651C647.664,933.992 657.814,945.635 670.315,945.635L1586.34,945.635C1598.85,945.635 1608.99,933.992 1608.99,919.651L1608.99,583.163Z" style="fill:rgb(255,166,48);"/>
|
||||||
|
<path d="M1624.98,583.163L1624.98,919.651C1624.98,944.11 1607.66,963.968 1586.34,963.968L670.315,963.968C648.993,963.968 631.682,944.11 631.682,919.651L631.682,583.163C631.682,558.704 648.993,538.846 670.315,538.846L1586.34,538.846C1607.66,538.846 1624.98,558.704 1624.98,583.163ZM1608.99,583.163C1608.99,568.822 1598.85,557.179 1586.34,557.179L670.315,557.179C657.814,557.179 647.664,568.822 647.664,583.163L647.664,919.651C647.664,933.992 657.814,945.635 670.315,945.635L1586.34,945.635C1598.85,945.635 1608.99,933.992 1608.99,919.651L1608.99,583.163Z" style="fill:white;"/>
|
||||||
|
</g>
|
||||||
|
<g transform="matrix(0.19416,0,0,0.275328,1052.99,601.372)">
|
||||||
|
<path d="M1608.99,571.746C1608.99,563.706 1600.46,557.179 1589.95,557.179L666.712,557.179C656.199,557.179 647.664,563.706 647.664,571.746L647.664,931.068C647.664,939.108 656.199,945.635 666.712,945.635L1589.95,945.635C1600.46,945.635 1608.99,939.108 1608.99,931.068L1608.99,571.746Z" style="fill:rgb(255,211,152);stroke:white;stroke-width:19.24px;stroke-linecap:round;"/>
|
||||||
|
</g>
|
||||||
|
<g transform="matrix(1.04373,0,0,1.13192,-345.04,-841.508)">
|
||||||
|
<g transform="matrix(50,0,0,50,1433.76,1475.25)">
|
||||||
|
</g>
|
||||||
|
<text x="1197.76px" y="1475.25px" style="font-family:'Nunito-Medium', 'Nunito';font-weight:500;font-size:50px;">R<tspan x="1230.81px " y="1475.25px ">e</tspan>spHell<tspan x="1405.76px " y="1475.25px ">o</tspan></text>
|
||||||
|
</g>
|
||||||
|
<g transform="matrix(1.04373,0,0,1.13192,-34.3588,-841.794)">
|
||||||
|
<g transform="matrix(41.6667,0,0,41.6667,1315.29,1464.53)">
|
||||||
|
</g>
|
||||||
|
<text x="1188.09px" y="1464.53px" style="font-family:'Nunito-SemiBold', 'Nunito';font-weight:600;font-size:41.667px;">Biscuit</text>
|
||||||
|
</g>
|
||||||
|
<g transform="matrix(-1.10076,0,0,0.321304,2401.96,1404.06)">
|
||||||
|
<g transform="matrix(-0.94819,0,0,3.52288,2021.14,-3818.47)">
|
||||||
|
<path d="M220.225,1263.96L207.725,1251.46L220.225,1238.96" style="fill:none;stroke:rgb(255,166,48);stroke-width:8.33px;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:10;"/>
|
||||||
|
<path d="M1607.34,1251.46L207.725,1251.46" style="fill:none;stroke:rgb(255,166,48);stroke-width:8.33px;stroke-linecap:round;stroke-dasharray:8.33,16.67,0,0;"/>
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
<g transform="matrix(0.54423,0,0,0.514519,523.603,1207.09)">
|
||||||
|
<path d="M1608.99,583.163C1608.99,568.822 1598.85,557.179 1586.34,557.179L670.315,557.179C657.814,557.179 647.664,568.822 647.664,583.163L647.664,919.651C647.664,933.992 657.814,945.635 670.315,945.635L1586.34,945.635C1598.85,945.635 1608.99,933.992 1608.99,919.651L1608.99,583.163Z" style="fill:rgb(255,166,48);"/>
|
||||||
|
<path d="M1624.98,583.163L1624.98,919.651C1624.98,944.11 1607.66,963.968 1586.34,963.968L670.315,963.968C648.993,963.968 631.682,944.11 631.682,919.651L631.682,583.163C631.682,558.704 648.993,538.846 670.315,538.846L1586.34,538.846C1607.66,538.846 1624.98,558.704 1624.98,583.163ZM1608.99,583.163C1608.99,568.822 1598.85,557.179 1586.34,557.179L670.315,557.179C657.814,557.179 647.664,568.822 647.664,583.163L647.664,919.651C647.664,933.992 657.814,945.635 670.315,945.635L1586.34,945.635C1598.85,945.635 1608.99,933.992 1608.99,919.651L1608.99,583.163Z" style="fill:white;"/>
|
||||||
|
</g>
|
||||||
|
<g transform="matrix(1.04373,0,0,1.13192,-323.596,-115.707)">
|
||||||
|
<g transform="matrix(50,0,0,50,1528.5,1528)">
|
||||||
|
</g>
|
||||||
|
<text x="1274.4px" y="1528px" style="font-family:'Nunito-Medium', 'Nunito';font-weight:500;font-size:50px;">Emp<tspan x="1375.85px 1394.1px " y="1528px 1528px ">ty</tspan>Data</text>
|
||||||
|
</g>
|
||||||
|
<g transform="matrix(1.16933e-17,1.13192,-0.102439,3.71795e-17,1384.12,272.481)">
|
||||||
|
<path d="M497.076,394.18L497.076,1793.56" style="fill:none;stroke:rgb(255,166,48);stroke-width:17.59px;stroke-linecap:round;"/>
|
||||||
|
</g>
|
||||||
|
<g transform="matrix(1.16933e-17,1.13192,-0.102439,3.71795e-17,1384.12,612.276)">
|
||||||
|
<path d="M497.076,394.18L497.076,1793.56" style="fill:none;stroke:rgb(255,166,48);stroke-width:17.59px;stroke-linecap:round;"/>
|
||||||
|
</g>
|
||||||
|
<g transform="matrix(0.377816,0,0,0.318513,1464.43,3.62207)">
|
||||||
|
<path d="M1608.99,599.153C1608.99,575.987 1594.37,557.179 1576.37,557.179L680.292,557.179C662.284,557.179 647.664,575.987 647.664,599.153L647.664,903.661C647.664,926.827 662.284,945.635 680.292,945.635L1576.37,945.635C1594.37,945.635 1608.99,926.827 1608.99,903.661L1608.99,599.153Z" style="fill:rgb(255,166,48);"/>
|
||||||
|
</g>
|
||||||
|
<g transform="matrix(1.04373,2.9937e-16,-2.74652e-16,1.13192,767.205,-815.996)">
|
||||||
|
<text x="1171.58px" y="1474.94px" style="font-family:'Nunito-Light', 'Nunito';font-weight:300;font-size:41.667px;fill:rgb(64,63,73);">r<tspan x="1185.58px " y="1474.94px ">e</tspan>sponder</text>
|
||||||
|
<g transform="matrix(41.6667,0,0,41.6667,1432.53,1516.61)">
|
||||||
|
</g>
|
||||||
|
<text x="1171.58px" y="1516.61px" style="font-family:'Nunito-Light', 'Nunito';font-weight:300;font-size:41.667px;fill:rgb(64,63,73);">aut<tspan x="1230.45px " y="1516.61px ">h</tspan>ent<tspan x="1313.16px 1322.41px 1341.33px 1363.08px 1377.16px " y="1516.61px 1516.61px 1516.61px 1516.61px 1516.61px ">icati</tspan>on</text>
|
||||||
|
</g>
|
||||||
|
<g transform="matrix(1.04373,1.80409e-17,1.85964e-17,1.13192,767.205,-611.456)">
|
||||||
|
<text x="1171.58px" y="1454.11px" style="font-family:'Nunito-Light', 'Nunito';font-weight:300;font-size:41.667px;fill:rgb(64,63,73);">init<tspan x="1227.49px " y="1454.11px ">i</tspan>at<tspan x="1272.24px " y="1454.11px ">o</tspan>r</text>
|
||||||
|
<text x="1171.58px" y="1495.78px" style="font-family:'Nunito-Light', 'Nunito';font-weight:300;font-size:41.667px;fill:rgb(64,63,73);">aut<tspan x="1230.45px " y="1495.78px ">h</tspan>ent<tspan x="1313.16px 1322.41px 1341.33px 1363.08px 1377.16px " y="1495.78px 1495.78px 1495.78px 1495.78px 1495.78px ">icati</tspan>on,</text>
|
||||||
|
<g transform="matrix(41.6667,0,0,41.6667,1464.49,1537.44)">
|
||||||
|
</g>
|
||||||
|
<text x="1171.58px" y="1537.44px" style="font-family:'Nunito-Light', 'Nunito';font-weight:300;font-size:41.667px;fill:rgb(64,63,73);">f<tspan x="1184.24px 1207.03px 1222.53px 1256.91px 1278.66px 1292.66px " y="1537.44px 1537.44px 1537.44px 1537.44px 1537.44px 1537.44px ">orward</tspan> secr<tspan x="1402.12px " y="1537.44px ">e</tspan>cy</text>
|
||||||
|
</g>
|
||||||
|
<g transform="matrix(1.04373,1.80409e-17,1.85964e-17,1.13192,705.967,-92.9691)">
|
||||||
|
<text x="1171.58px" y="1474.94px" style="font-family:'Nunito-Light', 'Nunito';font-weight:300;font-size:41.667px;fill:rgb(64,63,73);">ackno<tspan x="1278.49px 1313.28px 1324.95px " y="1474.94px 1474.94px 1474.94px ">wle</tspan>dges</text>
|
||||||
|
<g transform="matrix(41.6667,0,0,41.6667,1314.2,1516.61)">
|
||||||
|
</g>
|
||||||
|
<text x="1171.58px" y="1516.61px" style="font-family:'Nunito-Light', 'Nunito';font-weight:300;font-size:41.667px;fill:rgb(64,63,73);">InitC<tspan x="1254.78px " y="1516.61px ">o</tspan>nf</text>
|
||||||
|
</g>
|
||||||
|
<g transform="matrix(1.04373,1.72621e-17,1.94353e-17,1.13192,767.205,-321.469)">
|
||||||
|
<text x="1171.58px" y="1472.39px" style="font-family:'Nunito-Light', 'Nunito';font-weight:300;font-size:41.667px;fill:rgb(64,63,73);">OSK handed</text>
|
||||||
|
<g transform="matrix(41.6667,0,0,41.6667,1422.78,1514.06)">
|
||||||
|
</g>
|
||||||
|
<text x="1171.58px" y="1514.06px" style="font-family:'Nunito-Light', 'Nunito';font-weight:300;font-size:41.667px;fill:rgb(64,63,73);">t<tspan x="1185.33px " y="1514.06px ">o</tspan> W<tspan x="1264.74px 1273.99px 1287.99px " y="1514.06px 1514.06px 1514.06px ">ire</tspan>Guar<tspan x="1398.83px " y="1514.06px ">d</tspan></text>
|
||||||
|
</g>
|
||||||
|
<g transform="matrix(1.04373,0,0,1.13192,-159.675,-1425.03)">
|
||||||
|
<g transform="matrix(33.3333,0,0,33.3333,1376.21,1461.44)">
|
||||||
|
</g>
|
||||||
|
<text x="1171.58px" y="1461.44px" style="font-family:'Nunito-Medium', 'Nunito';font-weight:500;font-size:33.333px;fill:rgb(64,63,73);">Init<tspan x="1219.48px " y="1461.44px ">i</tspan>at<tspan x="1256.91px " y="1461.44px ">o</tspan>r Stat<tspan x="1358.41px " y="1461.44px ">e</tspan></text>
|
||||||
|
</g>
|
||||||
|
<g transform="matrix(1.04373,0,0,1.13192,-159.675,-1369.01)">
|
||||||
|
<g transform="matrix(33.3333,0,0,33.3333,1422.81,1461.44)">
|
||||||
|
</g>
|
||||||
|
<text x="1171.58px" y="1461.44px" style="font-family:'Nunito-Medium', 'Nunito';font-weight:500;font-size:33.333px;fill:rgb(64,63,73);">R<tspan x="1193.61px " y="1461.44px ">e</tspan>sponder Stat<tspan x="1405.01px " y="1461.44px ">e</tspan></text>
|
||||||
|
</g>
|
||||||
|
<g transform="matrix(1.04373,0,0,1.13192,-1040.69,-1406.95)">
|
||||||
|
<g transform="matrix(50,0,0,50,1434.05,1476.14)">
|
||||||
|
</g>
|
||||||
|
<text x="1257.1px" y="1476.14px" style="font-family:'Nunito-SemiBold', 'Nunito';font-weight:600;font-size:50px;fill:white;">Init<tspan x="1330.14px " y="1476.14px ">i</tspan>at<tspan x="1387.14px " y="1476.14px ">o</tspan>r</text>
|
||||||
|
</g>
|
||||||
|
<g transform="matrix(1.04373,0,0,1.13192,486.326,-1406.95)">
|
||||||
|
<g transform="matrix(50,0,0,50,1468.55,1476.14)">
|
||||||
|
</g>
|
||||||
|
<text x="1222.6px" y="1476.14px" style="font-family:'Nunito-SemiBold', 'Nunito';font-weight:600;font-size:50px;fill:white;">R<tspan x="1255.85px " y="1476.14px ">e</tspan>sponder</text>
|
||||||
|
</g>
|
||||||
|
<g transform="matrix(1.29981,-1.40964,1.29981,1.40964,-996.095,-284.091)">
|
||||||
|
<path d="M735.267,1542.91L717.276,1524.92L711.619,1548.57L735.267,1542.91Z" style="fill:rgb(179,178,182);"/>
|
||||||
|
<path d="M736.092,1546.36L712.445,1552.02L708.168,1547.74L713.825,1524.09L719.785,1522.41L737.776,1540.4L736.092,1546.36ZM735.267,1542.91L717.276,1524.92L711.619,1548.57L735.267,1542.91Z" style="fill:white;"/>
|
||||||
|
</g>
|
||||||
|
<g transform="matrix(1.29981,-1.40964,1.29981,1.40964,-996.095,-79.5508)">
|
||||||
|
<path d="M735.267,1542.91L717.276,1524.92L711.619,1548.57L735.267,1542.91Z" style="fill:rgb(179,178,182);"/>
|
||||||
|
<path d="M736.092,1546.36L712.445,1552.02L708.168,1547.74L713.825,1524.09L719.785,1522.41L737.776,1540.4L736.092,1546.36ZM735.267,1542.91L717.276,1524.92L711.619,1548.57L735.267,1542.91Z" style="fill:white;"/>
|
||||||
|
</g>
|
||||||
|
<g transform="matrix(1.29981,-1.40964,1.29981,1.40964,-996.095,207.55)">
|
||||||
|
<path d="M735.267,1542.91L717.276,1524.92L711.619,1548.57L735.267,1542.91Z" style="fill:rgb(179,178,182);"/>
|
||||||
|
<path d="M736.092,1546.36L712.445,1552.02L708.168,1547.74L713.825,1524.09L719.785,1522.41L737.776,1540.4L736.092,1546.36ZM735.267,1542.91L717.276,1524.92L711.619,1548.57L735.267,1542.91Z" style="fill:white;"/>
|
||||||
|
</g>
|
||||||
|
<g transform="matrix(1.04373,2.04033e-17,1.82707e-17,1.13192,287.154,-312.768)">
|
||||||
|
<g transform="matrix(41.6667,0,0,41.6667,1473.76,1457.69)">
|
||||||
|
</g>
|
||||||
|
<text x="1274.85px" y="1457.69px" style="font-family:'Nunito-Light', 'Nunito';font-weight:300;font-size:41.667px;fill:rgb(64,63,73);">handshak<tspan x="1451.8px " y="1457.69px ">e</tspan></text>
|
||||||
|
</g>
|
||||||
|
<g transform="matrix(1.04373,4.8711e-17,3.06091e-17,1.13192,312.355,-241.08)">
|
||||||
|
<g transform="matrix(41.6667,0,0,41.6667,1449.62,1457.69)">
|
||||||
|
</g>
|
||||||
|
<text x="1249.16px" y="1457.69px" style="font-family:'Nunito-Light', 'Nunito';font-weight:300;font-size:41.667px;fill:rgb(64,63,73);">l<tspan x="1262.7px 1273.62px 1296.24px 1319.87px 1332.03px 1357.66px 1382.66px 1406.07px 1427.66px " y="1457.69px 1457.69px 1457.69px 1457.69px 1457.69px 1457.69px 1457.69px 1457.69px 1457.69px ">ive phase</tspan></text>
|
||||||
|
</g>
|
||||||
|
<g transform="matrix(1.04373,0,0,1.24761,-135.752,-334.388)">
|
||||||
|
<g transform="matrix(1,-0,-0,0.90727,299.807,410.028)">
|
||||||
|
<path d="M1593.36,999.66L1602.74,980.91L1612.11,999.66C1607.42,994.973 1598.05,994.973 1593.36,999.66Z" style="fill:rgb(179,178,182);"/>
|
||||||
|
<path d="M1602.74,1027.14L1602.74,995.91" style="fill:none;stroke:rgb(179,178,182);stroke-width:6.25px;stroke-linecap:round;"/>
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
<g transform="matrix(-1.04373,1.52788e-16,-1.2782e-16,-1.24761,3835.73,3054.11)">
|
||||||
|
<g transform="matrix(-1,-1.22465e-16,1.11109e-16,-0.90727,3505.28,2305.97)">
|
||||||
|
<path d="M1612.11,1090.07L1602.74,1108.82L1593.36,1090.07C1598.05,1094.75 1607.42,1094.75 1612.11,1090.07Z" style="fill:rgb(179,178,182);"/>
|
||||||
|
<path d="M1602.74,1062.59L1602.74,1093.82" style="fill:none;stroke:rgb(179,178,182);stroke-width:6.25px;stroke-linecap:round;"/>
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 21 KiB |
|
Before Width: | Height: | Size: 134 KiB After Width: | Height: | Size: 138 KiB |
@@ -1,12 +1,15 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||||
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
|
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
|
||||||
<svg width="100%" height="100%" viewBox="0 0 2037 1491" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xml:space="preserve" xmlns:serif="http://www.serif.com/" style="fill-rule:evenodd;clip-rule:evenodd;stroke-linejoin:round;stroke-miterlimit:1.5;">
|
<svg width="100%" height="100%" viewBox="0 0 2037 1491" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xml:space="preserve" xmlns:serif="http://www.serif.com/" style="fill-rule:evenodd;clip-rule:evenodd;stroke-linejoin:round;stroke-miterlimit:1.5;">
|
||||||
<g id="ArtBoard1" transform="matrix(0.958104,0,0,0.883458,-169.743,-156.518)">
|
<g transform="matrix(0.958104,0,0,0.883458,-169.743,-156.518)">
|
||||||
<rect x="177.165" y="177.165" width="2125.98" height="1687.51" style="fill:none;"/>
|
<rect id="ArtBoard1" x="177.165" y="177.165" width="2125.98" height="1687.51" style="fill:none;"/>
|
||||||
<clipPath id="_clip1">
|
<clipPath id="_clip1">
|
||||||
<rect x="177.165" y="177.165" width="2125.98" height="1687.51"/>
|
<rect id="ArtBoard11" serif:id="ArtBoard1" x="177.165" y="177.165" width="2125.98" height="1687.51"/>
|
||||||
</clipPath>
|
</clipPath>
|
||||||
<g clip-path="url(#_clip1)">
|
<g clip-path="url(#_clip1)">
|
||||||
|
<g transform="matrix(1.04373,0,0,1.13192,177.165,177.165)">
|
||||||
|
<rect x="-16.526" y="0" width="2083.17" height="1490.84" style="fill:white;"/>
|
||||||
|
</g>
|
||||||
<g transform="matrix(0.377816,0,0,0.318513,-62.5845,3.62207)">
|
<g transform="matrix(0.377816,0,0,0.318513,-62.5845,3.62207)">
|
||||||
<path d="M1608.99,599.153C1608.99,575.987 1594.37,557.179 1576.37,557.179L680.292,557.179C662.284,557.179 647.664,575.987 647.664,599.153L647.664,903.661C647.664,926.827 662.284,945.635 680.292,945.635L1576.37,945.635C1594.37,945.635 1608.99,926.827 1608.99,903.661L1608.99,599.153Z" style="fill:rgb(247,4,132);"/>
|
<path d="M1608.99,599.153C1608.99,575.987 1594.37,557.179 1576.37,557.179L680.292,557.179C662.284,557.179 647.664,575.987 647.664,599.153L647.664,903.661C647.664,926.827 662.284,945.635 680.292,945.635L1576.37,945.635C1594.37,945.635 1608.99,926.827 1608.99,903.661L1608.99,599.153Z" style="fill:rgb(247,4,132);"/>
|
||||||
</g>
|
</g>
|
||||||
|
|||||||
|
Before Width: | Height: | Size: 21 KiB After Width: | Height: | Size: 21 KiB |
BIN
papers/graphics/rosenpass-wp-message-handling-code-rgb.pdf
Normal file
1009
papers/graphics/rosenpass-wp-message-handling-code-rgb.svg
Normal file
|
After Width: | Height: | Size: 97 KiB |