Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Make inputs to recv_mac and meta_recv_mac immutable #8

Merged
merged 5 commits into from
Jul 24, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
162 changes: 38 additions & 124 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
@@ -1,150 +1,64 @@
name: CI

on:
# Run CI on new pushes to the repo or any pull requests.
# If only the README file changed, ignore.
pull_request:
paths-ignore:
- README.md
push:
branches: master
paths-ignore:
- README.md
# Allow CI workflow to be run manually
workflow_dispatch:
# Run CI at least once a month no matter what
schedule:
- cron: '0 1 1 */1 *'
branches: ["**"]
paths-ignore: ["README.md", "CHANGELOG.md"]
pull_request:
branches: ["**"]
paths-ignore: ["README.md", "CHANGELOG.md"]

env:
CARGO_TERM_COLOR: always
RUSTFLAGS: "-D warnings"

jobs:
test:
strategy:
matrix:
platform:
- ubuntu-latest
- macos-latest
- windows-latest
toolchain:
- stable
- nightly
runs-on: ${{ matrix.platform }}
steps:
- name: Checkout sources
uses: actions/checkout@v2

- name: Install toolchain
uses: actions-rs/toolchain@v1
with:
toolchain: ${{ matrix.toolchain }}
override: true

- name: Run cargo test --no-default-features
env:
CARGO_INCREMENTAL: 0
RUSTFLAGS: -D warnings
uses: actions-rs/cargo@v1
with:
command: test
args: --no-default-features

- name: Run cargo test --all-features
env:
CARGO_INCREMENTAL: 0
RUSTFLAGS: -D warnings
uses: actions-rs/cargo@v1
with:
command: test
args: --all-features

cross-linux-test:
name: Test on Rust stable
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
rust_target:
# Other interesting archs here:
# https://github.com/rust-embedded/cross/tree/master/docker
- i686-unknown-linux-gnu
- powerpc-unknown-linux-gnu
timeout-minutes: 10
steps:
- name: Checkout sources
uses: actions/checkout@v2
include:
# 32-bit big-endian target
- target: powerpc-unknown-linux-gnu
deps: sudo apt update && sudo apt install gcc-multilib

- name: Install Rust stable
uses: actions-rs/toolchain@v1
with:
toolchain: stable
profile: minimal
target: ${{ matrix.rust_target }}
default: true

- name: Test
env:
CARGO_INCREMENTAL: 0
RUSTFLAGS: -D warnings
uses: actions-rs/cargo@v1
with:
# see https://github.com/rust-embedded/cross
use-cross: true
command: test
args: --all-features --target ${{ matrix.rust_target }}
# 64-bit target
- target: x86_64-unknown-linux-gnu
steps:
- uses: actions/checkout@v3
- uses: dtolnay/rust-toolchain@stable
- run: cargo test

rustfmt:
runs-on: ubuntu-latest
steps:
- name: Checkout sources
uses: actions/checkout@v2

- name: Install stable toolchain
uses: actions-rs/toolchain@v1
with:
profile: minimal
toolchain: stable
components: rustfmt
- uses: actions/checkout@v3
- uses: dtolnay/rust-toolchain@stable
- run: cargo fmt --all -- --check

- name: Run cargo fmt
uses: actions-rs/cargo@v1
with:
command: fmt
args: --all -- --check
clippy:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- uses: actions-rs/toolchain@v1
- uses: actions/checkout@v3
- uses: dtolnay/rust-toolchain@stable
with:
profile: minimal
toolchain: stable
components: clippy
- run: cargo clippy --all-features -- -D warnings

codecov:
# Test no_std build-only
build-nostd:
name: Build on no_std target (thumbv7em-none-eabi)
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@v2

- name: Install stable toolchain
uses: actions-rs/toolchain@v1
- uses: actions/checkout@v3
- uses: dtolnay/rust-toolchain@master
with:
toolchain: stable
override: true

- name: Run cargo-tarpaulin
uses: actions-rs/[email protected]
env:
CARGO_INCREMENTAL: 0
with:
version: 0.15.0
args: --all-features

- name: Upload to codecov.io
uses: codecov/[email protected]
with:
token: ${{secrets.CODECOV_TOKEN}}

- name: Archive code coverage results
uses: actions/upload-artifact@v1
with:
name: code-coverage-report
path: cobertura.xml
targets: thumbv7em-none-eabi
- uses: taiki-e/install-action@cargo-hack
# No default features build
- name: no_std / no feat
run: cargo build --target thumbv7em-none-eabi --release --no-default-features
- name: no_std / cargo hack
run: cargo hack build --target thumbv7em-none-eabi --release --each-feature --exclude-features default,std
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,10 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).

## Unrelease

* Made `(meta_)recv_mac` inputs take a `&[u8; N]` rather than a `&mut [u8]`

## [0.8.1] - 2022-10-10

### Changes
Expand Down
7 changes: 5 additions & 2 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ documentation = "https://docs.rs/strobe-rs"
description = "An implementation of the Strobe protocol framework in pure Rust"
readme = "README.md"
version = "0.8.1"
edition = "2018"
edition = "2021"
authors = ["Michael Rosenberg <[email protected]>"]
license = "MIT/Apache-2.0"
keywords = ["crypto", "strobe", "protocol", "framework", "no_std"]
Expand All @@ -20,14 +20,17 @@ serialize_secret_state = ["serde", "serde-big-array"]
bitflags = "1.3"
byteorder = { version = "1.4", default-features = false }
keccak = "0.1"
serde = { version = "1", optional = true, default-features = false, features = ["derive"] }
serde = { version = "1", optional = true, default-features = false, features = [
"derive",
] }
serde-big-array = { version = "0.4", optional = true }
subtle = { version = "2.4", default-features = false }
zeroize = { version = "1.5", features = ["derive"] }

[dev-dependencies]
criterion = { version = "0.5", features = ["html_reports"] }
hex = "0.4"
rand = "0.8.5"
serde = { version = "1", features = ["derive"] }
serde_json = "1"

Expand Down
55 changes: 39 additions & 16 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,37 +6,60 @@ strobe-rs
[![Version](https://img.shields.io/crates/v/strobe-rs.svg)](https://crates.io/crates/strobe-rs)
[![Docs](https://docs.rs/strobe-rs/badge.svg)](https://docs.rs/strobe-rs)

This is a relatively barebones, `no_std` implementation of the [Strobe protocol framework][strobe] in pure Rust. It is intended to be used as a library to build other protocols and frameworks. This implementation currently only supports Keccak-f\[1600\] as the internal permutation function, which is the largest possible block size, so big deal.
This is a pure Rust, `no_std` implementation of the [Strobe protocol framework][strobe]. It is intended to be used as a library to build other protocols and frameworks. This implementation currently only supports Keccak-f\[1600\] as the internal permutation function, which is the largest possible block size, so big deal.

[strobe]: https://strobe.sourceforge.io/

Example
-------

A simple [program](examples/basic.rs) that encrypts and decrypts a message:
A simple [program](examples/basic.rs) that does authenticated encryption and decryption:

```rust
use strobe_rs::{SecParam, Strobe};

fn main() {
let mut rx = Strobe::new(b"correctnesstest", SecParam::B256);
let mut tx = Strobe::new(b"correctnesstest", SecParam::B256);

rx.key(b"the-combination-on-my-luggage", false);
tx.key(b"the-combination-on-my-luggage", false);
use rand::RngCore;

let mut msg = b"Attack at dawn".to_vec();
rx.send_enc(msg.as_mut_slice(), false);
// NOTE: This is just a simple authenticated encryption scheme. For a robust AEAD construction,
// see the example at https://strobe.sourceforge.io/examples/aead/

// Rename for clarity. `msg` has been encrypted in-place.
let mut ciphertext = msg;
fn main() {
let mut rng = rand::thread_rng();

tx.recv_enc(ciphertext.as_mut_slice(), false);
// Sender and receiver
let mut tx = Strobe::new(b"correctnesstest", SecParam::B256);
let mut rx = Strobe::new(b"correctnesstest", SecParam::B256);

// And back again.
// Key both sides with a predetermined key
let k = b"the-combination-on-my-luggage";
tx.key(k, false);
rx.key(k, false);

// Have the transmitter sample and send a nonce (192 bits) in the clear
let mut nonce = [0u8; 24];
rng.fill_bytes(&mut nonce);
rx.recv_clr(&nonce, false);
tx.send_clr(&nonce, false);

// Have the transmitter send an authenticated ciphertext (with a 256 bit MAC)
let orig_msg = b"groceries: kaymac, ajvar, cream, diced onion, red pepper, grilled meat";
let mut msg_buf = *orig_msg;
tx.send_enc(&mut msg_buf, false);
let mut mac = [0u8; 32];
tx.send_mac(&mut mac, false);

// Rename for clarity. `msg_buf` has been encrypted in-place.
let mut ciphertext = msg_buf;

// Have the receiver receive the ciphertext and MAC
rx.recv_enc(ciphertext.as_mut_slice(), false);
let res = rx.recv_mac(&mac);

// Check that the MAC verifies
assert!(res.is_ok());
// Check that the decrypted ciphertext equals the original plaintext
let round_trip_msg = ciphertext;

assert_eq!(&round_trip_msg, b"Attack at dawn");
assert_eq!(&round_trip_msg, orig_msg);
}
```

Expand Down
45 changes: 34 additions & 11 deletions examples/basic.rs
Original file line number Diff line number Diff line change
@@ -1,22 +1,45 @@
use strobe_rs::{SecParam, Strobe};

use rand::RngCore;

// NOTE: This is just a simple authenticated encryption scheme. For a robust AEAD construction,
// see the example at https://strobe.sourceforge.io/examples/aead/

fn main() {
let mut rx = Strobe::new(b"correctnesstest", SecParam::B256);
let mut rng = rand::thread_rng();

// Sender and receiver
let mut tx = Strobe::new(b"correctnesstest", SecParam::B256);
let mut rx = Strobe::new(b"correctnesstest", SecParam::B256);

rx.key(b"the-combination-on-my-luggage", false);
tx.key(b"the-combination-on-my-luggage", false);
// Key both sides with a predetermined key
let k = b"the-combination-on-my-luggage";
tx.key(k, false);
rx.key(k, false);

let mut msg = b"Attack at dawn".to_vec();
rx.send_enc(msg.as_mut_slice(), false);
// Have the transmitter sample and send a nonce (192 bits) in the clear
let mut nonce = [0u8; 24];
rng.fill_bytes(&mut nonce);
rx.recv_clr(&nonce, false);
tx.send_clr(&nonce, false);

// Rename for clarity. `msg` has been encrypted in-place.
let mut ciphertext = msg;
// Have the transmitter send an authenticated ciphertext (with a 256 bit MAC)
let orig_msg = b"groceries: kaymac, ajvar, cream, diced onion, red pepper, grilled meat";
let mut msg_buf = *orig_msg;
tx.send_enc(&mut msg_buf, false);
let mut mac = [0u8; 32];
tx.send_mac(&mut mac, false);

tx.recv_enc(ciphertext.as_mut_slice(), false);
// Rename for clarity. `msg_buf` has been encrypted in-place.
let mut ciphertext = msg_buf;

// And back again.
let round_trip_msg = ciphertext;
// Have the receiver receive the ciphertext and MAC
rx.recv_enc(ciphertext.as_mut_slice(), false);
let res = rx.recv_mac(&mac);

assert_eq!(&round_trip_msg, b"Attack at dawn");
// Check that the MAC verifies
assert!(res.is_ok());
// Check that the decrypted ciphertext equals the original plaintext
let round_trip_msg = ciphertext;
assert_eq!(&round_trip_msg, orig_msg);
}
Loading
Loading