Skip to content

Commit

Permalink
Add Marvin toolkit container (#400)
Browse files Browse the repository at this point in the history
This contains a Docker image which can be used for testing for the Marvin Attack:

https://people.redhat.com/~hkario/marvin/
  • Loading branch information
xuganyu96 authored Feb 13, 2024
1 parent 4cb8aec commit d011ca5
Show file tree
Hide file tree
Showing 4 changed files with 235 additions and 0 deletions.
13 changes: 13 additions & 0 deletions marvin-toolkit/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
[package]
name = "rust-crypto"
version = "0.1.0"
edition = "2021"

[dependencies]
anyhow = "1"
clap = { version = "4", features = ["derive"] }
rsa = "0.9"

[patch.crates-io]
rsa = { git = "https://github.com/RustCrypto/RSA", branch = "const-crypto-biguint" }
crypto-bigint = { git = "https://github.com/RustCrypto/crypto-bigint", branch = "master" }
23 changes: 23 additions & 0 deletions marvin-toolkit/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
FROM python:3.12-bookworm

# Create non-root user
RUN adduser rustcrypto --disabled-password --gecos ""

USER rustcrypto

# Install Rust
RUN curl -sSf https://sh.rustup.rs | sh -s -- -y
ENV PATH="/home/rustcrypto/.cargo/bin:${PATH}"

# Clone the marvin-toolkit repository
RUN cd $HOME \
&& git clone https://github.com/tomato42/marvin-toolkit.git \
&& cd marvin-toolkit \
&& chmod +x *.sh \
&& ./step0.sh
WORKDIR "/home/rustcrypto/marvin-toolkit"

# Generating private keys, ciphertexts, building RustCrypto/RSA, should all be done at runtime
COPY --chmod=777 entrypoint.sh ./entrypoint.sh

ENTRYPOINT ["./entrypoint.sh"]
66 changes: 66 additions & 0 deletions marvin-toolkit/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
# Marvin tool-kit integration
This document describes the procedure for replicating the analysis for the Marvin attack. This analysis is best done on a container for reproducibility.

**TL;DR**:
```bash
# Build the image
docker build -t marvin:latest .

# Create the output directory and allow container to write to it
mkdir -p outputs
chmod a+rw outputs

# Run the analysis
docker run -d --rm \
--name marvin \
-v $(pwd)/outputs:/home/rustcrypto/marvin-toolkit/outputs \
-v $(pwd)/Cargo.toml:/home/rustcrypto/marvin-toolkit/example/rust-crypto/Cargo.toml \
marvin:latest

# Use "docker logs -f marvin" to read live output

# Read the output
cat outputs/results/report.txt
```

## Adjusting analysis parameters
For more help on the options pass in the `-h` flag in the `docker run` command:

```
docker run ... marvin:latest -h
```

There are two main parameters of the analysis: RSA key size and the number of repetitions during ciphertext generation.

RSA key size is specified through `-s <1024|2048|4096>`. The number of repetition is specified through `-n <num>`. A larger repetition number will increase the confidence of the analysis, but will make the analysis take longer. The default key size is 2048 and the default repetition count is 100,000.

```bash
# Run analysis for RSA 4096 with 1 million repetition
docker run -d --rm \
--name marvin \
marvin:latest -s 4096 -n 1000000
```

## Extracting keys, ciphertexts, and analysis results (WIP)
After the analysis is done, the generate keys, ciphertexts, and the analysis outputs are all copied into the directory `/home/rustcrypto/marvin-toolkit/outputs`. To extract and preserve these artifacts, mount a volume into this directory, such as using a bind mount:

```bash
mkdir -p outputs
chmod a+rw outputs

# Mount
docker run -d --rm --name "marvin" \
-v $(pwd)/outputs:/home/rustcrypto/marvin-toolkit/outputs \
marvin:latest
```

## Compile test harness with custom `Cargo.toml`
The test harness is compiled at container run-time, so a custom `Cargo.toml` can be passed into the container at runtime to compile the test harness using custom versions of `RustCrypto/RSA` and/or `RustCrypto/crypto-bigint`:

```bash
docker run -d --rm --name "marvin" \
-v $(pwd)/Cargo.toml:/home/rustcrypto/marvin-toolkit/example/rust-crypto/Cargo.toml \
marvin:latest
```

If no `Cargo.toml` is specified, the default one will use `rsa = 0.9`
133 changes: 133 additions & 0 deletions marvin-toolkit/entrypoint.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,133 @@
#!/bin/bash

# Build the test harness
cd example/rust-crypto
cargo update --quiet
cargo build --profile release --quiet
cd ~/marvin-toolkit

# Parse CLI inputs to $size and $repeat
size=2048
repeat=100000

# Function to display help message
display_help() {
echo "Usage: $0 [-s SIZE] [-n NUMBER] [-h]"
echo " -s SIZE Set the RSA key size (1024, 2048, or 4096; default: 2048)"
echo " -n NUMBER Set the repeat number (integer; default: 100000)"
echo " -h Display this help message"
}

# Parse command-line arguments using getopts
while getopts ":s:n:h" opt; do
case $opt in
s)
size=$OPTARG
if [[ ! "$size" =~ ^(1024|2048|4096)$ ]]; then
echo "Error: Invalid size. Please choose 1024, 2048, or 4096."
exit 1
fi
;;
n)
repeat=$OPTARG
if ! [[ "$repeat" =~ ^[0-9]+$ ]]; then
echo "Error: Invalid number. Please specify a valid integer."
exit 1
fi
;;
h)
display_help
exit 0
;;
\?)
echo "Error: Invalid option -$OPTARG"
display_help
exit 1
;;
:)
echo "Error: Option -$OPTARG requires an argument."
display_help
exit 1
;;
esac
done
size_bytes=$(($size / 8))

# Step 1: Generate key pairs
. ./certgen/certgen/lib.sh
name="rsa${size}"
tmp_file="$(mktemp)"
if ! x509KeyGen -s $size $name &> "$tmp_file"; then
echo "ERROR $size bit key generation failed" >&2
cat "$tmp_file" >&2
exit 1
fi
if ! x509SelfSign $name &> "$tmp_file"; then
echo "ERROR: $size bit key self-signing failed" >&2
cat "$tmp_file" >&2
exit 1
fi

echo "RSA $size bit private key in old OpenSSL PEM format is in" $(x509Key $name)
echo "RSA $size bit private key in old OpenSSL DER format is in" $(x509Key --der $name)
echo "RSA $size bit private key in PKCS#8 PEM format is in" $(x509Key --pkcs8 $name)
echo "RSA $size bit private key in PKCS#8 DER format is in" $(x509Key --der --pkcs8 $name)
echo "RSA $size bit private key in PKCS#12 format is in" $(x509Key --with-cert --pkcs12 $name)
echo "RSA $size bit self-signed certificate is in" $(x509Cert $name)
echo

# Generate ciphertexts
case $size in
1024)
PYTHONPATH=tlsfuzzer ./marvin-venv/bin/python ./step2.py \
-c rsa1024/cert.pem -o rsa1024_repeat \
--repeat ${repeat} --verbose \
no_structure no_padding=48 signature_padding=8 \
valid_repeated_byte_payload="118 0xff" \
valid_repeated_byte_payload="118 0x01" \
valid=48 header_only \
no_header_with_payload=48 zero_byte_in_padding="48 4" \
valid=0 valid=118
;;
2048)
PYTHONPATH=tlsfuzzer ./marvin-venv/bin/python ./step2.py \
-c rsa2048/cert.pem -o rsa2048_repeat \
--repeat ${repeat} --verbose \
no_structure no_padding=48 signature_padding=8 \
valid_repeated_byte_payload="246 0xff" \
valid_repeated_byte_payload="246 0x01" \
valid=48 header_only \
no_header_with_payload=48 zero_byte_in_padding="48 4" \
valid=0 valid=192 valid=246
;;
4096)
PYTHONPATH=tlsfuzzer ./marvin-venv/bin/python ./step2.py \
-c rsa4096/cert.pem -o rsa4096_repeat \
--repeat ${repeat} --verbose \
no_structure no_padding=48 signature_padding=8 \
valid_repeated_byte_payload="502 0xff" \
valid_repeated_byte_payload="502 0x01" \
valid=48 header_only \
no_header_with_payload=48 zero_byte_in_padding="48 4" \
valid=0 valid=192 valid=502
;;
esac

# Run decryptions and analyze data
echo "Starting decryption"
./example/rust-crypto/target/release/rust-crypto \
-i rsa${size}_repeat/ciphers.bin \
-o rsa${size}_repeat/raw_times.csv -k rsa${size}/pkcs8.pem -n $size_bytes
echo "Decryptions finished"
PYTHONPATH=tlsfuzzer marvin-venv/bin/python3 tlsfuzzer/tlsfuzzer/extract.py \
-l rsa${size}_repeat/log.csv --raw-times rsa${size}_repeat/raw_times.csv \
-o rsa${size}_repeat/ \
--clock-frequency 1000
PYTHONPATH=tlsfuzzer marvin-venv/bin/python3 tlsfuzzer/tlsfuzzer/analysis.py \
-o rsa${size}_repeat/ --verbose

# Copy over the keys and the results, if the results directory exists
if [[ -d ~/marvin-toolkit/outputs ]]; then
cp -r rsa${size} ~/marvin-toolkit/outputs/keys
cp -r rsa${size}_repeat ~/marvin-toolkit/outputs/results
fi

0 comments on commit d011ca5

Please sign in to comment.