Compare commits
64 Commits
hybrid-pqc
...
develop
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
4339600730 | ||
|
|
298db9ea99 | ||
|
|
ba0d717d88 | ||
|
|
0185d1e443 | ||
|
|
191d043cc4 | ||
|
|
6b8aa3aaf3 | ||
|
|
5fdc6e0739 | ||
|
|
af763450a9 | ||
|
|
eaeb927d92 | ||
|
|
c160b034ef | ||
|
|
6ed83c34c7 | ||
|
|
e5ba9db644 | ||
|
|
3a5adfc5af | ||
|
|
09a6b3ce1a | ||
|
|
778102712f | ||
|
|
67e3d46291 | ||
|
|
8a53986961 | ||
|
|
87f0711284 | ||
|
|
96af5e81a5 | ||
|
|
e3d2e7d778 | ||
|
|
8868752e37 | ||
|
|
a274a512f7 | ||
|
|
f0e87ee813 | ||
|
|
3813cacea7 | ||
|
|
e9ea05f888 | ||
|
|
55f7e47423 | ||
|
|
fbf07d7476 | ||
|
|
6fb7e194eb | ||
|
|
94b0beed4b | ||
|
|
99f81adc55 | ||
|
|
cae2088f36 | ||
|
|
f25cdd6acc | ||
|
|
645c1ba3a7 | ||
|
|
bcd382e5e9 | ||
|
|
a88a1b2a22 | ||
|
|
5f7eb3177b | ||
|
|
3091b5a29d | ||
|
|
a1d6ed0223 | ||
|
|
be42b47caf | ||
|
|
4cc1b4fddf | ||
|
|
d0cdbec5ce | ||
|
|
22192a37d2 | ||
|
|
c168141b60 | ||
|
|
80b82ffd42 | ||
|
|
6d5ea16f2d | ||
|
|
2560b6661c | ||
|
|
752db8cc90 | ||
|
|
ca65902a8f | ||
|
|
03031e6970 | ||
|
|
7769e783bb | ||
|
|
3135c13e6b | ||
|
|
d8512b4417 | ||
|
|
9a2ef0bf75 | ||
|
|
73c60d8740 | ||
|
|
963549f9bb | ||
|
|
98ecdec453 | ||
|
|
a222986995 | ||
|
|
8733d6585f | ||
|
|
684d37fa03 | ||
|
|
0db393bd1e | ||
|
|
6b5f6e53eb | ||
|
|
f6e9e00b87 | ||
|
|
0d0460f016 | ||
|
|
9ab3bc977c |
38
.github/workflows/boards_build.yml
vendored
38
.github/workflows/boards_build.yml
vendored
@@ -1,38 +0,0 @@
|
|||||||
---
|
|
||||||
name: Build supported boards
|
|
||||||
on:
|
|
||||||
push:
|
|
||||||
paths:
|
|
||||||
- 'patches/tock/*'
|
|
||||||
- 'third_party/tock/**'
|
|
||||||
pull_request:
|
|
||||||
types: [opened, synchronize, reopened]
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
build_boards:
|
|
||||||
strategy:
|
|
||||||
matrix:
|
|
||||||
os: [ubuntu-latest, macos-10.15]
|
|
||||||
runs-on: ${{ matrix.os }}
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v2
|
|
||||||
with:
|
|
||||||
submodules: "true"
|
|
||||||
- name: Install Rust toolchain
|
|
||||||
run: rustup show
|
|
||||||
- uses: actions/setup-python@v1
|
|
||||||
with:
|
|
||||||
python-version: 3.7
|
|
||||||
- name: Install Python dependencies
|
|
||||||
run: python -m pip install --upgrade pip setuptools wheel
|
|
||||||
- name: Set up OpenSK
|
|
||||||
run: ./setup.sh
|
|
||||||
|
|
||||||
- name: Building board nrf52840dk_opensk
|
|
||||||
run: ./deploy.py --board=nrf52840dk_opensk --no-app --programmer=none
|
|
||||||
- name: Building board nrf52840_dongle_opensk
|
|
||||||
run: ./deploy.py --board=nrf52840_dongle_opensk --no-app --programmer=none
|
|
||||||
- name: Building board nrf52840_dongle_dfu
|
|
||||||
run: ./deploy.py --board=nrf52840_dongle_dfu --no-app --programmer=none
|
|
||||||
- name: Building board nrf52840_mdk_dfu
|
|
||||||
run: ./deploy.py --board=nrf52840_mdk_dfu --no-app --programmer=none
|
|
||||||
10
.github/workflows/cargo_audit.yml
vendored
10
.github/workflows/cargo_audit.yml
vendored
@@ -8,16 +8,12 @@ jobs:
|
|||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
if: github.repository == 'google/OpenSK'
|
if: github.repository == 'google/OpenSK'
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v2
|
- uses: actions/checkout@v4
|
||||||
with:
|
with:
|
||||||
submodules: "true"
|
submodules: "true"
|
||||||
- name: Install Rust toolchain
|
- uses: actions/setup-python@v5
|
||||||
run: rustup show
|
|
||||||
- uses: actions/setup-python@v1
|
|
||||||
with:
|
with:
|
||||||
python-version: 3.7
|
python-version: "3.10"
|
||||||
- name: Install Python dependencies
|
|
||||||
run: python -m pip install --upgrade pip setuptools wheel
|
|
||||||
- name: Set up OpenSK
|
- name: Set up OpenSK
|
||||||
run: ./setup.sh
|
run: ./setup.sh
|
||||||
- uses: actions-rs/audit-check@v1
|
- uses: actions-rs/audit-check@v1
|
||||||
|
|||||||
19
.github/workflows/cargo_bloat.yml
vendored
19
.github/workflows/cargo_bloat.yml
vendored
@@ -6,42 +6,35 @@ jobs:
|
|||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
# Setup
|
# Setup
|
||||||
- uses: actions/setup-python@v1
|
- uses: actions/setup-python@v5
|
||||||
with:
|
with:
|
||||||
python-version: 3.7
|
python-version: "3.10"
|
||||||
- name: Install Python dependencies
|
|
||||||
run: python -m pip install --upgrade pip setuptools wheel
|
|
||||||
- uses: actions-rs/cargo@v1
|
- uses: actions-rs/cargo@v1
|
||||||
with:
|
with:
|
||||||
command: install
|
command: install
|
||||||
args: cargo-bloat
|
args: cargo-bloat
|
||||||
|
|
||||||
# First run: PR
|
# First run: PR
|
||||||
- uses: actions/checkout@v2
|
- uses: actions/checkout@v4
|
||||||
with:
|
with:
|
||||||
submodules: true
|
submodules: true
|
||||||
- name: Install Rust toolchain
|
|
||||||
run: rustup show
|
|
||||||
- name: Set up OpenSK
|
- name: Set up OpenSK
|
||||||
run: ./setup.sh
|
run: ./setup.sh
|
||||||
- name: Run bloat on the PR
|
- name: Run bloat on the PR
|
||||||
run: RUSTFLAGS="-C link-arg=-icf=all -C force-frame-pointers=no" cargo bloat --release --target=thumbv7em-none-eabi --features=with_ctap1,vendor_hid --crates >> .github/workflows/bloat_output_new.txt
|
run: RUSTFLAGS="-C link-arg=-icf=all -C force-frame-pointers=no -C link-arg=-Tnrf52840_layout.ld" cargo bloat --release --target=thumbv7em-none-eabi --features=config_command,with_ctap1 --crates >> .github/workflows/bloat_output_new.txt
|
||||||
|
|
||||||
# Second run: PR
|
# Second run: PR
|
||||||
- uses: actions/checkout@v2
|
- uses: actions/checkout@v4
|
||||||
with:
|
with:
|
||||||
submodules: true
|
submodules: true
|
||||||
ref: ${{ github.base_ref }}
|
ref: ${{ github.base_ref }}
|
||||||
path: OpenSK_base
|
path: OpenSK_base
|
||||||
- name: Install old Rust toolchain
|
|
||||||
working-directory: ./OpenSK_base
|
|
||||||
run: rustup show
|
|
||||||
- name: Set up OpenSK
|
- name: Set up OpenSK
|
||||||
working-directory: ./OpenSK_base
|
working-directory: ./OpenSK_base
|
||||||
run: ./setup.sh
|
run: ./setup.sh
|
||||||
- name: Run bloat on base
|
- name: Run bloat on base
|
||||||
working-directory: ./OpenSK_base
|
working-directory: ./OpenSK_base
|
||||||
run: RUSTFLAGS="-C link-arg=-icf=all -C force-frame-pointers=no" cargo bloat --release --target=thumbv7em-none-eabi --features=with_ctap1,vendor_hid --crates >> "$GITHUB_WORKSPACE/.github/workflows/bloat_output_old.txt"
|
run: RUSTFLAGS="-C link-arg=-icf=all -C force-frame-pointers=no -C link-arg=-Tnrf52840_layout.ld" cargo bloat --release --target=thumbv7em-none-eabi --features=config_command,with_ctap1 --crates >> "$GITHUB_WORKSPACE/.github/workflows/bloat_output_old.txt"
|
||||||
|
|
||||||
- name: Run output formatter to echo workflow command
|
- name: Run output formatter to echo workflow command
|
||||||
run: ./.github/workflows/bloat_formatter.sh bloat_output_new.txt bloat_output_old.txt bloat_comment.md
|
run: ./.github/workflows/bloat_formatter.sh bloat_output_new.txt bloat_output_old.txt bloat_comment.md
|
||||||
|
|||||||
96
.github/workflows/cargo_check.yml
vendored
96
.github/workflows/cargo_check.yml
vendored
@@ -1,96 +0,0 @@
|
|||||||
name: Cargo check
|
|
||||||
on:
|
|
||||||
push:
|
|
||||||
paths:
|
|
||||||
- 'examples/*.rs'
|
|
||||||
- 'libraries/**/*.rs'
|
|
||||||
- 'src/**/*.rs'
|
|
||||||
- 'patches/**'
|
|
||||||
- '**/Cargo.toml'
|
|
||||||
- '.cargo/config'
|
|
||||||
- '!third_party/**'
|
|
||||||
pull_request:
|
|
||||||
types: [opened, synchronize, reopened]
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
cargo_check:
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v2
|
|
||||||
with:
|
|
||||||
submodules: "true"
|
|
||||||
- name: Install Rust toolchain
|
|
||||||
run: rustup show
|
|
||||||
- uses: actions/setup-python@v1
|
|
||||||
with:
|
|
||||||
python-version: 3.7
|
|
||||||
- name: Install Python dependencies
|
|
||||||
run: python -m pip install --upgrade pip setuptools wheel
|
|
||||||
- name: Set up OpenSK
|
|
||||||
run: ./setup.sh
|
|
||||||
|
|
||||||
- name: Check OpenSK w/o features
|
|
||||||
uses: actions-rs/cargo@v1
|
|
||||||
with:
|
|
||||||
command: check
|
|
||||||
args: --target thumbv7em-none-eabi --release
|
|
||||||
|
|
||||||
- name: Check OpenSK with_ctap1
|
|
||||||
uses: actions-rs/cargo@v1
|
|
||||||
with:
|
|
||||||
command: check
|
|
||||||
args: --target thumbv7em-none-eabi --release --features with_ctap1
|
|
||||||
|
|
||||||
- name: Check OpenSK vendor_hid
|
|
||||||
uses: actions-rs/cargo@v1
|
|
||||||
with:
|
|
||||||
command: check
|
|
||||||
args: --target thumbv7em-none-eabi --release --features vendor_hid
|
|
||||||
|
|
||||||
- name: Check OpenSK ed25519
|
|
||||||
uses: actions-rs/cargo@v1
|
|
||||||
with:
|
|
||||||
command: check
|
|
||||||
args: --target thumbv7em-none-eabi --release --features ed25519
|
|
||||||
|
|
||||||
- name: Check OpenSK debug_ctap
|
|
||||||
uses: actions-rs/cargo@v1
|
|
||||||
with:
|
|
||||||
command: check
|
|
||||||
args: --target thumbv7em-none-eabi --release --features debug_ctap
|
|
||||||
|
|
||||||
- name: Check OpenSK panic_console
|
|
||||||
uses: actions-rs/cargo@v1
|
|
||||||
with:
|
|
||||||
command: check
|
|
||||||
args: --target thumbv7em-none-eabi --release --features panic_console
|
|
||||||
|
|
||||||
- name: Check OpenSK debug_allocations
|
|
||||||
uses: actions-rs/cargo@v1
|
|
||||||
with:
|
|
||||||
command: check
|
|
||||||
args: --target thumbv7em-none-eabi --release --features debug_allocations
|
|
||||||
|
|
||||||
- name: Check OpenSK verbose
|
|
||||||
uses: actions-rs/cargo@v1
|
|
||||||
with:
|
|
||||||
command: check
|
|
||||||
args: --target thumbv7em-none-eabi --release --features verbose
|
|
||||||
|
|
||||||
- name: Check OpenSK debug_ctap,with_ctap1
|
|
||||||
uses: actions-rs/cargo@v1
|
|
||||||
with:
|
|
||||||
command: check
|
|
||||||
args: --target thumbv7em-none-eabi --release --features debug_ctap,with_ctap1
|
|
||||||
|
|
||||||
- name: Check OpenSK debug_ctap,with_ctap1,vendor_hid,ed25519,panic_console,debug_allocations,verbose
|
|
||||||
uses: actions-rs/cargo@v1
|
|
||||||
with:
|
|
||||||
command: check
|
|
||||||
args: --target thumbv7em-none-eabi --release --features debug_ctap,with_ctap1,vendor_hid,ed25519,panic_console,debug_allocations,verbose
|
|
||||||
|
|
||||||
- name: Check examples
|
|
||||||
uses: actions-rs/cargo@v1
|
|
||||||
with:
|
|
||||||
command: check
|
|
||||||
args: --target thumbv7em-none-eabi --release --examples
|
|
||||||
34
.github/workflows/cargo_clippy.yml
vendored
34
.github/workflows/cargo_clippy.yml
vendored
@@ -1,34 +0,0 @@
|
|||||||
---
|
|
||||||
name: Cargo Clippy
|
|
||||||
on:
|
|
||||||
push:
|
|
||||||
pull_request:
|
|
||||||
types: [opened, synchronize, reopened]
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
cargo_clippy:
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v2
|
|
||||||
with:
|
|
||||||
submodules: "true"
|
|
||||||
- name: Install Rust toolchain
|
|
||||||
run: rustup show
|
|
||||||
- uses: actions/setup-python@v1
|
|
||||||
with:
|
|
||||||
python-version: 3.7
|
|
||||||
- name: Install Python dependencies
|
|
||||||
run: python -m pip install --upgrade pip setuptools wheel
|
|
||||||
- name: Set up OpenSK
|
|
||||||
run: ./setup.sh
|
|
||||||
|
|
||||||
- uses: actions-rs/clippy-check@v1
|
|
||||||
with:
|
|
||||||
token: ${{ secrets.GITHUB_TOKEN }}
|
|
||||||
args: --all-targets --features std
|
|
||||||
- name: Deny Clippy warnings (std)
|
|
||||||
run: cargo clippy --all-targets --features std -- -A clippy::new_without_default -D warnings
|
|
||||||
- name: Deny Clippy warnings (all)
|
|
||||||
run: cargo clippy --all-targets --features std,with_ctap1,ed25519,vendor_hid -- -A clippy::new_without_default -D warnings
|
|
||||||
- name: Deny Clippy warnings (all, nfc)
|
|
||||||
run: cargo clippy --all-targets --features std,with_ctap1,with_nfc,ed25519,vendor_hid -- -A clippy::new_without_default -D warnings
|
|
||||||
79
.github/workflows/cargo_fmt.yml
vendored
79
.github/workflows/cargo_fmt.yml
vendored
@@ -1,79 +0,0 @@
|
|||||||
name: Cargo format
|
|
||||||
on:
|
|
||||||
push:
|
|
||||||
paths:
|
|
||||||
- 'examples/*.rs'
|
|
||||||
- 'libraries/**/*.rs'
|
|
||||||
- 'src/**/*.rs'
|
|
||||||
- 'tools/**/*.rs'
|
|
||||||
- 'patches/**'
|
|
||||||
- '**/Cargo.toml'
|
|
||||||
- '.cargo/config'
|
|
||||||
- '!third_party/**'
|
|
||||||
pull_request:
|
|
||||||
types: [opened, synchronize, reopened]
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
cargo_format:
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v2
|
|
||||||
with:
|
|
||||||
submodules: "true"
|
|
||||||
- name: Install Rust toolchain
|
|
||||||
run: rustup show
|
|
||||||
- uses: actions/setup-python@v1
|
|
||||||
with:
|
|
||||||
python-version: 3.7
|
|
||||||
- name: Install Python dependencies
|
|
||||||
run: python -m pip install --upgrade pip setuptools wheel
|
|
||||||
- name: Set up OpenSK
|
|
||||||
run: ./setup.sh
|
|
||||||
|
|
||||||
- name: Cargo format src/
|
|
||||||
uses: actions-rs/cargo@v1
|
|
||||||
with:
|
|
||||||
command: fmt
|
|
||||||
args: --all -- --check
|
|
||||||
|
|
||||||
- name: Cargo format fuzz/
|
|
||||||
uses: actions-rs/cargo@v1
|
|
||||||
with:
|
|
||||||
command: fmt
|
|
||||||
args: --manifest-path fuzz/Cargo.toml --all -- --check
|
|
||||||
|
|
||||||
- name: Cargo format libraries/cbor
|
|
||||||
uses: actions-rs/cargo@v1
|
|
||||||
with:
|
|
||||||
command: fmt
|
|
||||||
args: --manifest-path libraries/cbor/Cargo.toml --all -- --check
|
|
||||||
|
|
||||||
- name: Cargo format libraries/cbor/fuzz
|
|
||||||
uses: actions-rs/cargo@v1
|
|
||||||
with:
|
|
||||||
command: fmt
|
|
||||||
args: --manifest-path libraries/cbor/fuzz/Cargo.toml --all -- --check
|
|
||||||
|
|
||||||
- name: Cargo format libraries/crypto
|
|
||||||
uses: actions-rs/cargo@v1
|
|
||||||
with:
|
|
||||||
command: fmt
|
|
||||||
args: --manifest-path libraries/crypto/Cargo.toml --all -- --check
|
|
||||||
|
|
||||||
- name: Cargo format libraries/persistent_store
|
|
||||||
uses: actions-rs/cargo@v1
|
|
||||||
with:
|
|
||||||
command: fmt
|
|
||||||
args: --manifest-path libraries/persistent_store/Cargo.toml --all -- --check
|
|
||||||
|
|
||||||
- name: Cargo format tools/heapviz
|
|
||||||
uses: actions-rs/cargo@v1
|
|
||||||
with:
|
|
||||||
command: fmt
|
|
||||||
args: --manifest-path tools/heapviz/Cargo.toml --all -- --check
|
|
||||||
|
|
||||||
- name: Cargo format bootloader
|
|
||||||
uses: actions-rs/cargo@v1
|
|
||||||
with:
|
|
||||||
command: fmt
|
|
||||||
args: --manifest-path bootloader/Cargo.toml --all -- --check
|
|
||||||
32
.github/workflows/cargo_fuzz.yml
vendored
32
.github/workflows/cargo_fuzz.yml
vendored
@@ -1,32 +0,0 @@
|
|||||||
---
|
|
||||||
name: Cargo fuzz build
|
|
||||||
on:
|
|
||||||
push:
|
|
||||||
pull_request:
|
|
||||||
types: [opened, synchronize, reopened]
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
build_fuzzing:
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v2
|
|
||||||
with:
|
|
||||||
submodules: "true"
|
|
||||||
- name: Install Rust toolchain
|
|
||||||
run: rustup show
|
|
||||||
- uses: actions/setup-python@v1
|
|
||||||
with:
|
|
||||||
python-version: 3.7
|
|
||||||
- name: Install Python dependencies
|
|
||||||
run: python -m pip install --upgrade pip setuptools wheel
|
|
||||||
- name: Set up OpenSK
|
|
||||||
run: ./setup.sh
|
|
||||||
- name: Set up fuzzing
|
|
||||||
run: ./fuzzing_setup.sh
|
|
||||||
|
|
||||||
- name: Cargo fuzz build
|
|
||||||
run: cargo fuzz build
|
|
||||||
- name: Cargo fuzz build (libraries/cbor)
|
|
||||||
run: cd libraries/cbor && cargo fuzz build && cd ../..
|
|
||||||
- name: Cargo fuzz build (libraries/persistent_store)
|
|
||||||
run: cd libraries/persistent_store && cargo fuzz build && cd ../..
|
|
||||||
37
.github/workflows/cbor_test.yml
vendored
37
.github/workflows/cbor_test.yml
vendored
@@ -1,37 +0,0 @@
|
|||||||
---
|
|
||||||
name: CBOR tests
|
|
||||||
on:
|
|
||||||
push:
|
|
||||||
paths:
|
|
||||||
- 'libraries/cbor/**'
|
|
||||||
pull_request:
|
|
||||||
types: [opened, synchronize, reopened]
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
cbor_test:
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v2
|
|
||||||
with:
|
|
||||||
submodules: "true"
|
|
||||||
- name: Install Rust toolchain
|
|
||||||
run: rustup show
|
|
||||||
- uses: actions/setup-python@v1
|
|
||||||
with:
|
|
||||||
python-version: 3.7
|
|
||||||
- name: Install Python dependencies
|
|
||||||
run: python -m pip install --upgrade pip setuptools wheel
|
|
||||||
- name: Set up OpenSK
|
|
||||||
run: ./setup.sh
|
|
||||||
|
|
||||||
- name: Unit testing of CBOR library (release mode)
|
|
||||||
uses: actions-rs/cargo@v1
|
|
||||||
with:
|
|
||||||
command: test
|
|
||||||
args: --manifest-path libraries/cbor/Cargo.toml --release
|
|
||||||
|
|
||||||
- name: Unit testing of CBOR library (debug mode)
|
|
||||||
uses: actions-rs/cargo@v1
|
|
||||||
with:
|
|
||||||
command: test
|
|
||||||
args: --manifest-path libraries/cbor/Cargo.toml
|
|
||||||
31
.github/workflows/ci.yml
vendored
Normal file
31
.github/workflows/ci.yml
vendored
Normal file
@@ -0,0 +1,31 @@
|
|||||||
|
name: Continuous Integration
|
||||||
|
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
branches:
|
||||||
|
- develop
|
||||||
|
pull_request:
|
||||||
|
branches:
|
||||||
|
- develop
|
||||||
|
schedule:
|
||||||
|
- cron: 30 1 * * 2 # every Tuesday at 1:30 UTC
|
||||||
|
|
||||||
|
concurrency:
|
||||||
|
group: ci-${{ github.ref }}
|
||||||
|
cancel-in-progress: ${{ github.event_name == 'pull_request' }}
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
runtests:
|
||||||
|
strategy:
|
||||||
|
matrix:
|
||||||
|
os: [ubuntu-latest, macos-latest]
|
||||||
|
runs-on: ${{ matrix.os }}
|
||||||
|
permissions:
|
||||||
|
contents: read
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v4
|
||||||
|
- uses: actions/setup-python@v5
|
||||||
|
with:
|
||||||
|
python-version: "3.10"
|
||||||
|
- run: ./setup.sh
|
||||||
|
- run: ./run_desktop_tests.sh
|
||||||
4
.github/workflows/cifuzz.yml
vendored
4
.github/workflows/cifuzz.yml
vendored
@@ -1,6 +1,6 @@
|
|||||||
name: CIFuzz
|
name: CIFuzz
|
||||||
on:
|
on:
|
||||||
pull_request:
|
push:
|
||||||
branches:
|
branches:
|
||||||
- develop
|
- develop
|
||||||
jobs:
|
jobs:
|
||||||
@@ -21,7 +21,7 @@ jobs:
|
|||||||
fuzz-seconds: 600
|
fuzz-seconds: 600
|
||||||
dry-run: false
|
dry-run: false
|
||||||
- name: Upload Crash
|
- name: Upload Crash
|
||||||
uses: actions/upload-artifact@v1
|
uses: actions/upload-artifact@v4
|
||||||
if: failure() && steps.build.outcome == 'success'
|
if: failure() && steps.build.outcome == 'success'
|
||||||
with:
|
with:
|
||||||
name: artifacts
|
name: artifacts
|
||||||
|
|||||||
19
.github/workflows/coveralls.yml
vendored
19
.github/workflows/coveralls.yml
vendored
@@ -3,7 +3,6 @@ name: OpenSK code coverage report
|
|||||||
on:
|
on:
|
||||||
push:
|
push:
|
||||||
paths:
|
paths:
|
||||||
- 'src/**/*.rs'
|
|
||||||
- 'libraries/**/*.rs'
|
- 'libraries/**/*.rs'
|
||||||
pull_request:
|
pull_request:
|
||||||
types: [opened, synchronize, reopened]
|
types: [opened, synchronize, reopened]
|
||||||
@@ -14,35 +13,35 @@ jobs:
|
|||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v2
|
- uses: actions/checkout@v4
|
||||||
with:
|
with:
|
||||||
submodules: "true"
|
submodules: "true"
|
||||||
- name: Install Rust toolchain
|
- name: Install Rust toolchain
|
||||||
run: rustup show
|
run: rustup show
|
||||||
- uses: actions/setup-python@v1
|
- uses: actions/setup-python@v5
|
||||||
with:
|
with:
|
||||||
python-version: 3.7
|
python-version: "3.10"
|
||||||
- name: Install Python dependencies
|
|
||||||
run: python -m pip install --upgrade pip setuptools wheel
|
|
||||||
- name: Set up OpenSK
|
- name: Set up OpenSK
|
||||||
run: ./setup.sh
|
run: ./setup.sh
|
||||||
- name: Install llvm tools
|
- name: Install llvm tools
|
||||||
run: rustup component add llvm-tools-preview
|
run: rustup +nightly component add llvm-tools-preview
|
||||||
|
|
||||||
- name: Install grcov
|
- name: Install grcov
|
||||||
run: if [[ ! -e ~/.cargo/bin/grcov ]]; then cargo +stable install grcov; fi
|
run: if [[ ! -e ~/.cargo/bin/grcov ]]; then cargo +stable install grcov; fi
|
||||||
- uses: actions-rs/cargo@v1
|
- uses: actions-rs/cargo@v1
|
||||||
with:
|
with:
|
||||||
|
toolchain: nightly
|
||||||
command: test
|
command: test
|
||||||
args: --features "with_ctap1,vendor_hid,ed25519,with_nfc,std" --no-fail-fast
|
args: --manifest-path libraries/opensk/Cargo.toml --features "std,with_ctap1,vendor_hid,ed25519" --no-fail-fast
|
||||||
env:
|
env:
|
||||||
RUSTFLAGS: "-Zinstrument-coverage"
|
RUSTFLAGS: "-Cinstrument-coverage"
|
||||||
LLVM_PROFILE_FILE: "opensk-%p-%m.profraw"
|
LLVM_PROFILE_FILE: "opensk-%p-%m.profraw"
|
||||||
- name: Run grcov
|
- name: Run grcov
|
||||||
run: grcov . --binary-path ./target/debug/ --source-dir . --output-type lcov --ignore-not-existing ---output-path ./lcov.info --ignore "/*" --ignore "examples/*" --ignore "third_party/*"
|
run: RUSTUP_TOOLCHAIN=nightly grcov . --binary-path ./libraries/opensk/target/debug/ --source-dir libraries/opensk/ --output-type lcov --ignore-not-existing --output-path ./lcov.info --ignore "/*" --ignore "examples/*" --ignore "third_party/*"
|
||||||
- uses: coverallsapp/github-action@1.1.3
|
- uses: coverallsapp/github-action@1.1.3
|
||||||
name: upload report to coveralls
|
name: upload report to coveralls
|
||||||
with:
|
with:
|
||||||
github-token: ${{ secrets.GITHUB_TOKEN }}
|
github-token: ${{ secrets.GITHUB_TOKEN }}
|
||||||
path-to-lcov: "./lcov.info"
|
path-to-lcov: "./lcov.info"
|
||||||
|
base-path: "libraries/opensk"
|
||||||
|
|
||||||
|
|||||||
41
.github/workflows/crypto_test.yml
vendored
41
.github/workflows/crypto_test.yml
vendored
@@ -1,41 +0,0 @@
|
|||||||
---
|
|
||||||
name: Crypto library tests
|
|
||||||
on:
|
|
||||||
push:
|
|
||||||
paths:
|
|
||||||
- 'libraries/crypto/**'
|
|
||||||
pull_request:
|
|
||||||
types: [opened, synchronize, reopened]
|
|
||||||
paths:
|
|
||||||
- 'libraries/crypto/**'
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
crypto_test:
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v2
|
|
||||||
with:
|
|
||||||
submodules: "true"
|
|
||||||
- name: Install Rust toolchain
|
|
||||||
run: rustup show
|
|
||||||
- uses: actions/setup-python@v1
|
|
||||||
with:
|
|
||||||
python-version: 3.7
|
|
||||||
- name: Install Python dependencies
|
|
||||||
run: python -m pip install --upgrade pip setuptools wheel
|
|
||||||
- name: Set up OpenSK
|
|
||||||
run: ./setup.sh
|
|
||||||
|
|
||||||
- run: echo "RUSTFLAGS=-C target-feature=+aes" >> $GITHUB_ENV
|
|
||||||
|
|
||||||
- name: Unit testing of crypto library (release mode)
|
|
||||||
uses: actions-rs/cargo@v1
|
|
||||||
with:
|
|
||||||
command: test
|
|
||||||
args: --manifest-path libraries/crypto/Cargo.toml --release --features std
|
|
||||||
|
|
||||||
- name: Unit testing of crypto library (debug mode)
|
|
||||||
uses: actions-rs/cargo@v1
|
|
||||||
with:
|
|
||||||
command: test
|
|
||||||
args: --manifest-path libraries/crypto/Cargo.toml --features std
|
|
||||||
34
.github/workflows/heapviz_test.yml
vendored
34
.github/workflows/heapviz_test.yml
vendored
@@ -1,34 +0,0 @@
|
|||||||
---
|
|
||||||
name: Heapviz tool tests
|
|
||||||
on:
|
|
||||||
push:
|
|
||||||
paths:
|
|
||||||
- 'tools/heapviz/**'
|
|
||||||
pull_request:
|
|
||||||
types: [opened, synchronize, reopened]
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
heapviz_test:
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v2
|
|
||||||
- name: Install ncurses
|
|
||||||
run: sudo apt-get install libncurses-dev
|
|
||||||
|
|
||||||
- name: Check heapviz tool
|
|
||||||
uses: actions-rs/cargo@v1
|
|
||||||
with:
|
|
||||||
command: check
|
|
||||||
args: --manifest-path tools/heapviz/Cargo.toml
|
|
||||||
|
|
||||||
- name: Unit testing of heapviz tool (debug mode)
|
|
||||||
uses: actions-rs/cargo@v1
|
|
||||||
with:
|
|
||||||
command: test
|
|
||||||
args: --manifest-path tools/heapviz/Cargo.toml
|
|
||||||
|
|
||||||
- name: Unit testing of heapviz tool (release mode)
|
|
||||||
uses: actions-rs/cargo@v1
|
|
||||||
with:
|
|
||||||
command: test
|
|
||||||
args: --manifest-path tools/heapviz/Cargo.toml --release
|
|
||||||
8
.github/workflows/mdlint.yml
vendored
8
.github/workflows/mdlint.yml
vendored
@@ -12,10 +12,10 @@ jobs:
|
|||||||
mdlint:
|
mdlint:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v2
|
- uses: actions/checkout@v4
|
||||||
- name: markdownlint-cli
|
- name: markdownlint-cli
|
||||||
uses: nosborn/github-action-markdown-cli@v1.1.1
|
uses: nosborn/github-action-markdown-cli@v3
|
||||||
with:
|
with:
|
||||||
files: '**/*.md'
|
files: '**/*.md'
|
||||||
ignore_files: "third_party/*"
|
config_file: '.markdownlint.json'
|
||||||
config_file: ".markdownlint.json"
|
ignore_files: 'third_party/*'
|
||||||
|
|||||||
40
.github/workflows/opensk_build.yml
vendored
40
.github/workflows/opensk_build.yml
vendored
@@ -1,40 +0,0 @@
|
|||||||
---
|
|
||||||
name: OpenSK build
|
|
||||||
on:
|
|
||||||
push:
|
|
||||||
pull_request:
|
|
||||||
types: [opened, synchronize, reopened]
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
build_ctap2:
|
|
||||||
strategy:
|
|
||||||
matrix:
|
|
||||||
os: [ubuntu-latest, macos-10.15]
|
|
||||||
runs-on: ${{ matrix.os }}
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v2
|
|
||||||
with:
|
|
||||||
submodules: "true"
|
|
||||||
- name: Install Rust toolchain
|
|
||||||
run: rustup show
|
|
||||||
- uses: actions/setup-python@v1
|
|
||||||
with:
|
|
||||||
python-version: 3.7
|
|
||||||
- name: Install Python dependencies
|
|
||||||
run: python -m pip install --upgrade pip setuptools wheel
|
|
||||||
- name: Set up OpenSK
|
|
||||||
run: ./setup.sh
|
|
||||||
|
|
||||||
- name: Building sha256sum tool
|
|
||||||
uses: actions-rs/cargo@v1
|
|
||||||
with:
|
|
||||||
command: build
|
|
||||||
args: --manifest-path third_party/tock/tools/sha256sum/Cargo.toml
|
|
||||||
|
|
||||||
- name: Building OpenSK
|
|
||||||
uses: actions-rs/cargo@v1
|
|
||||||
with:
|
|
||||||
command: build
|
|
||||||
args: --release --target=thumbv7em-none-eabi --features with_ctap1,vendor_hid
|
|
||||||
- name: Compute SHA-256 sum
|
|
||||||
run: ./third_party/tock/tools/sha256sum/target/debug/sha256sum target/thumbv7em-none-eabi/release/ctap2
|
|
||||||
52
.github/workflows/opensk_test.yml
vendored
52
.github/workflows/opensk_test.yml
vendored
@@ -1,52 +0,0 @@
|
|||||||
---
|
|
||||||
name: OpenSK tests
|
|
||||||
on:
|
|
||||||
push:
|
|
||||||
paths:
|
|
||||||
- 'src/**/*.rs'
|
|
||||||
pull_request:
|
|
||||||
types: [opened, synchronize, reopened]
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
ctap2_test:
|
|
||||||
name: CTAP2 unit tests
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v2
|
|
||||||
with:
|
|
||||||
submodules: "true"
|
|
||||||
- name: Install Rust toolchain
|
|
||||||
run: rustup show
|
|
||||||
- uses: actions/setup-python@v1
|
|
||||||
with:
|
|
||||||
python-version: 3.7
|
|
||||||
- name: Install Python dependencies
|
|
||||||
run: python -m pip install --upgrade pip setuptools wheel
|
|
||||||
- name: Set up OpenSK
|
|
||||||
run: ./setup.sh
|
|
||||||
|
|
||||||
- name: Unit testing of CTAP2 (release mode)
|
|
||||||
uses: actions-rs/cargo@v1
|
|
||||||
with:
|
|
||||||
command: test
|
|
||||||
args: --release --features std
|
|
||||||
|
|
||||||
- name: Unit testing of CTAP2 (debug mode)
|
|
||||||
uses: actions-rs/cargo@v1
|
|
||||||
with:
|
|
||||||
command: test
|
|
||||||
args: --features std
|
|
||||||
|
|
||||||
- name: Unit testing of CTAP2 (release mode + CTAP1)
|
|
||||||
uses: actions-rs/cargo@v1
|
|
||||||
with:
|
|
||||||
command: test
|
|
||||||
args: --release --features std,with_ctap1
|
|
||||||
|
|
||||||
- name: Unit testing of CTAP2 (debug mode + CTAP1)
|
|
||||||
uses: actions-rs/cargo@v1
|
|
||||||
with:
|
|
||||||
command: test
|
|
||||||
args: --features std,with_ctap1
|
|
||||||
|
|
||||||
29
.github/workflows/persistent_store_test.yml
vendored
29
.github/workflows/persistent_store_test.yml
vendored
@@ -1,29 +0,0 @@
|
|||||||
---
|
|
||||||
name: Persistent store tests
|
|
||||||
on:
|
|
||||||
push:
|
|
||||||
paths:
|
|
||||||
- 'libraries/peristent_store/**'
|
|
||||||
pull_request:
|
|
||||||
types: [opened, synchronize, reopened]
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
persistent_store_test:
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v2
|
|
||||||
|
|
||||||
- name: Install Rust toolchain
|
|
||||||
run: rustup show
|
|
||||||
|
|
||||||
- name: Unit testing of Persistent store library (release mode)
|
|
||||||
uses: actions-rs/cargo@v1
|
|
||||||
with:
|
|
||||||
command: test
|
|
||||||
args: --manifest-path libraries/persistent_store/Cargo.toml --release --features=std
|
|
||||||
|
|
||||||
- name: Unit testing of Persistent store library (debug mode)
|
|
||||||
uses: actions-rs/cargo@v1
|
|
||||||
with:
|
|
||||||
command: test
|
|
||||||
args: --manifest-path libraries/persistent_store/Cargo.toml --features=std
|
|
||||||
46
.github/workflows/python.yml
vendored
46
.github/workflows/python.yml
vendored
@@ -1,46 +0,0 @@
|
|||||||
name: pylint
|
|
||||||
on:
|
|
||||||
push:
|
|
||||||
paths:
|
|
||||||
- '**/*.py'
|
|
||||||
- '.pylintrc'
|
|
||||||
- '!third_party/**'
|
|
||||||
pull_request:
|
|
||||||
types: [opened, synchronize, reopened]
|
|
||||||
jobs:
|
|
||||||
pylint:
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
strategy:
|
|
||||||
matrix:
|
|
||||||
python-version: [3.6, 3.7, 3.8, 3.9]
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v2
|
|
||||||
- name: Set up Python ${{ matrix.python-version }}
|
|
||||||
uses: actions/setup-python@v1
|
|
||||||
with:
|
|
||||||
python-version: ${{ matrix.python-version }}
|
|
||||||
- name: Install dependencies
|
|
||||||
run: |
|
|
||||||
python -m pip install --upgrade pip setuptools wheel
|
|
||||||
pip install 'tockloader==1.5' pylint
|
|
||||||
- name: Register matcher
|
|
||||||
run: echo ::add-matcher::./.github/python_matcher.json
|
|
||||||
- name: Test code with pylint
|
|
||||||
run: ./tools/run_pylint.sh
|
|
||||||
|
|
||||||
yapf:
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v2
|
|
||||||
- name: Set up Python 3.7
|
|
||||||
uses: actions/setup-python@v1
|
|
||||||
with:
|
|
||||||
python-version: 3.7
|
|
||||||
- name: Install dependencies
|
|
||||||
run: |
|
|
||||||
python -m pip install --upgrade pip setuptools wheel
|
|
||||||
pip install 'yapf>=0.30.0' tockloader
|
|
||||||
- name: Test code formatting with yapf
|
|
||||||
run: |
|
|
||||||
echo ::add-matcher::./.github/python_matcher.json
|
|
||||||
yapf --style=yapf --recursive --exclude third_party --diff .
|
|
||||||
12
.github/workflows/reproducible.yml
vendored
12
.github/workflows/reproducible.yml
vendored
@@ -9,20 +9,18 @@ jobs:
|
|||||||
check_hashes:
|
check_hashes:
|
||||||
strategy:
|
strategy:
|
||||||
matrix:
|
matrix:
|
||||||
os: [ubuntu-latest, macos-10.15]
|
os: [ubuntu-latest, macos-latest]
|
||||||
fail-fast: false
|
fail-fast: false
|
||||||
runs-on: ${{ matrix.os }}
|
runs-on: ${{ matrix.os }}
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v2
|
- uses: actions/checkout@v4
|
||||||
with:
|
with:
|
||||||
submodules: "true"
|
submodules: "true"
|
||||||
- name: Install Rust toolchain
|
- name: Install Rust toolchain
|
||||||
run: rustup show
|
run: rustup show
|
||||||
- uses: actions/setup-python@v1
|
- uses: actions/setup-python@v5
|
||||||
with:
|
with:
|
||||||
python-version: 3.7
|
python-version: "3.10"
|
||||||
- name: Install Python dependencies
|
|
||||||
run: python -m pip install --upgrade pip setuptools wheel
|
|
||||||
- name: Set up OpenSK
|
- name: Set up OpenSK
|
||||||
run: ./setup.sh
|
run: ./setup.sh
|
||||||
|
|
||||||
@@ -32,7 +30,7 @@ jobs:
|
|||||||
run: ./maintainers/reproduce_hashes.sh
|
run: ./maintainers/reproduce_hashes.sh
|
||||||
|
|
||||||
- name: Upload reproduced binaries
|
- name: Upload reproduced binaries
|
||||||
uses: actions/upload-artifact@v1
|
uses: actions/upload-artifact@v4
|
||||||
with:
|
with:
|
||||||
name: reproduced-${{ matrix.os }}
|
name: reproduced-${{ matrix.os }}
|
||||||
path: reproducible/reproduced.tar
|
path: reproducible/reproduced.tar
|
||||||
|
|||||||
39
.github/workflows/rng256_test.yml
vendored
39
.github/workflows/rng256_test.yml
vendored
@@ -1,39 +0,0 @@
|
|||||||
---
|
|
||||||
name: RNG library tests
|
|
||||||
on:
|
|
||||||
push:
|
|
||||||
paths:
|
|
||||||
- 'libraries/rng256/**'
|
|
||||||
pull_request:
|
|
||||||
types: [opened, synchronize, reopened]
|
|
||||||
paths:
|
|
||||||
- 'libraries/rng256/**'
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
rng256_test:
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v2
|
|
||||||
with:
|
|
||||||
submodules: "true"
|
|
||||||
- name: Install Rust toolchain
|
|
||||||
run: rustup show
|
|
||||||
- uses: actions/setup-python@v1
|
|
||||||
with:
|
|
||||||
python-version: 3.7
|
|
||||||
- name: Install Python dependencies
|
|
||||||
run: python -m pip install --upgrade pip setuptools wheel
|
|
||||||
- name: Set up OpenSK
|
|
||||||
run: ./setup.sh
|
|
||||||
|
|
||||||
- name: Unit testing of rng256library (release mode)
|
|
||||||
uses: actions-rs/cargo@v1
|
|
||||||
with:
|
|
||||||
command: test
|
|
||||||
args: --manifest-path libraries/rng256/Cargo.toml --release --features std
|
|
||||||
|
|
||||||
- name: Unit testing of rng256 library (debug mode)
|
|
||||||
uses: actions-rs/cargo@v1
|
|
||||||
with:
|
|
||||||
command: test
|
|
||||||
args: --manifest-path libraries/rng256/Cargo.toml --features std
|
|
||||||
6
.gitignore
vendored
6
.gitignore
vendored
@@ -1,7 +1,7 @@
|
|||||||
fuzz/artifacts
|
libraries/**/Cargo.lock
|
||||||
fuzz/corpus
|
|
||||||
fuzz/coverage
|
|
||||||
target/
|
target/
|
||||||
|
/build/
|
||||||
|
/py_virtual_env/
|
||||||
|
|
||||||
# Local installation of elf2tab.
|
# Local installation of elf2tab.
|
||||||
/elf2tab/
|
/elf2tab/
|
||||||
|
|||||||
@@ -1,35 +1,22 @@
|
|||||||
{
|
{
|
||||||
"default": true,
|
"default": true,
|
||||||
"heading-style": {
|
"MD003": {
|
||||||
"style": "atx"
|
"style": "atx"
|
||||||
},
|
},
|
||||||
"no-trailing-spaces": {
|
"MD007": {
|
||||||
|
"indent": 4
|
||||||
|
},
|
||||||
|
"MD009": {
|
||||||
"br_spaces": 0,
|
"br_spaces": 0,
|
||||||
"strict": true
|
"strict": true
|
||||||
},
|
},
|
||||||
"ul-indent": {
|
"MD013": {
|
||||||
"indent": 4
|
|
||||||
},
|
|
||||||
"line-length": {
|
|
||||||
"line_length": 80,
|
"line_length": 80,
|
||||||
"code_blocks": false
|
"code_blocks": false
|
||||||
},
|
},
|
||||||
"list-marker-space": {
|
"MD033": {
|
||||||
"ol_single": 2,
|
|
||||||
"ol_multi": 2,
|
|
||||||
"ul_single": 3,
|
|
||||||
"ul_multi": 3
|
|
||||||
},
|
|
||||||
"no-inline-html": {
|
|
||||||
"allowed_elements": [
|
"allowed_elements": [
|
||||||
"img"
|
"img"
|
||||||
]
|
]
|
||||||
},
|
|
||||||
"fenced-code-language": true,
|
|
||||||
"code-block-style": {
|
|
||||||
"style": "fenced"
|
|
||||||
},
|
|
||||||
"code-fence-style": {
|
|
||||||
"style": "backtick"
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -437,6 +437,6 @@ valid-metaclass-classmethod-first-arg=mcs
|
|||||||
|
|
||||||
# Exceptions that will emit a warning when being caught. Defaults to
|
# Exceptions that will emit a warning when being caught. Defaults to
|
||||||
# "Exception"
|
# "Exception"
|
||||||
overgeneral-exceptions=StandardError,
|
overgeneral-exceptions=builtins.StandardError,
|
||||||
Exception,
|
builtins.Exception,
|
||||||
BaseException
|
builtins.BaseException
|
||||||
|
|||||||
27
CITATION.cff
Normal file
27
CITATION.cff
Normal file
@@ -0,0 +1,27 @@
|
|||||||
|
cff-version: 1.2.0
|
||||||
|
message: "If you use this software, please cite it as below."
|
||||||
|
repository-code: "https://github.com/google/OpenSK"
|
||||||
|
license: "Apache-2.0"
|
||||||
|
preferred-citation:
|
||||||
|
type: article
|
||||||
|
authors:
|
||||||
|
- family-names: "Ghinea"
|
||||||
|
given-names: "Diana"
|
||||||
|
- family-names: "Kaczmarczyck"
|
||||||
|
given-names: "Fabian"
|
||||||
|
- family-names: "Pullman"
|
||||||
|
given-names: "Jennifer"
|
||||||
|
- family-names: "Cretin"
|
||||||
|
given-names: "Julien"
|
||||||
|
- family-names: "Kölbl"
|
||||||
|
given-names: "Stefan"
|
||||||
|
- family-names: "Invernizzi"
|
||||||
|
given-names: "Luca"
|
||||||
|
- family-names: "Bursztein"
|
||||||
|
given-names: "Elie"
|
||||||
|
- family-names: "Picod"
|
||||||
|
given-names: "Jean-Michel"
|
||||||
|
title: "Hybrid Post-Quantum Signatures in Hardware Security Keys"
|
||||||
|
journal: "4th ACNS Workshop on Secure Cryptographic Implementation"
|
||||||
|
year: 2023
|
||||||
|
month: 6
|
||||||
837
Cargo.lock
generated
837
Cargo.lock
generated
File diff suppressed because it is too large
Load Diff
41
Cargo.toml
41
Cargo.toml
@@ -5,38 +5,46 @@ authors = [
|
|||||||
"Fabian Kaczmarczyck <kaczmarczyck@google.com>",
|
"Fabian Kaczmarczyck <kaczmarczyck@google.com>",
|
||||||
"Guillaume Endignoux <guillaumee@google.com>",
|
"Guillaume Endignoux <guillaumee@google.com>",
|
||||||
"Jean-Michel Picod <jmichel@google.com>",
|
"Jean-Michel Picod <jmichel@google.com>",
|
||||||
|
"Julien Cretin <cretin@google.com>",
|
||||||
]
|
]
|
||||||
license = "Apache-2.0"
|
license = "Apache-2.0"
|
||||||
edition = "2018"
|
edition = "2018"
|
||||||
|
|
||||||
|
[target.'cfg(any(target_arch = "arm", target_arch = "riscv32"))'.dependencies.libtock_runtime]
|
||||||
|
path = "third_party/libtock-rs/runtime"
|
||||||
|
default-features = false
|
||||||
|
features = ["no_auto_layout", "no_debug_memop"]
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
libtock_core = { path = "third_party/libtock-rs/core" }
|
libtock_buttons = { path = "third_party/libtock-rs/apis/buttons" }
|
||||||
|
libtock_platform = { path = "third_party/libtock-rs/platform" }
|
||||||
libtock_drivers = { path = "third_party/libtock-drivers" }
|
libtock_drivers = { path = "third_party/libtock-drivers" }
|
||||||
|
libtock_alarm = { path = "third_party/libtock-rs/apis/alarm" }
|
||||||
|
libtock_console = { path = "third_party/libtock-rs/apis/console" }
|
||||||
|
libtock_leds = { path = "third_party/libtock-rs/apis/leds" }
|
||||||
lang_items = { path = "third_party/lang-items" }
|
lang_items = { path = "third_party/lang-items" }
|
||||||
|
opensk = { path = "libraries/opensk", default-features = false }
|
||||||
sk-cbor = { path = "libraries/cbor" }
|
sk-cbor = { path = "libraries/cbor" }
|
||||||
crypto = { path = "libraries/crypto" }
|
crypto = { path = "libraries/crypto" }
|
||||||
rng256 = { path = "libraries/rng256" }
|
|
||||||
persistent_store = { path = "libraries/persistent_store" }
|
persistent_store = { path = "libraries/persistent_store" }
|
||||||
|
libtock_unittest = { path = "third_party/libtock-rs/unittest", optional = true }
|
||||||
byteorder = { version = "1", default-features = false }
|
byteorder = { version = "1", default-features = false }
|
||||||
arrayref = "0.3.6"
|
arrayref = "0.3.6"
|
||||||
subtle = { version = "2.2", default-features = false, features = ["nightly"] }
|
rand_core = "0.6.4"
|
||||||
embedded-time = "0.12.1"
|
|
||||||
arbitrary = { version = "0.4.7", features = ["derive"], optional = true }
|
|
||||||
rand = { version = "0.8.4", optional = true }
|
|
||||||
ed25519-compact = { version = "1", default-features = false, optional = true }
|
ed25519-compact = { version = "1", default-features = false, optional = true }
|
||||||
dilithium = { path = "third_party/dilithium" }
|
|
||||||
|
|
||||||
[features]
|
[features]
|
||||||
|
config_command = ["opensk/config_command"]
|
||||||
debug_allocations = ["lang_items/debug_allocations"]
|
debug_allocations = ["lang_items/debug_allocations"]
|
||||||
debug_ctap = ["libtock_drivers/debug_ctap"]
|
debug_ctap = ["libtock_drivers/debug_ctap", "opensk/debug_ctap"]
|
||||||
panic_console = ["lang_items/panic_console"]
|
panic_console = ["lang_items/panic_console"]
|
||||||
std = ["crypto/std", "dilithium/std", "lang_items/std", "persistent_store/std", "rng256/std", "rand"]
|
std = ["crypto/std", "lang_items/std", "persistent_store/std", "opensk/std", "libtock_unittest"]
|
||||||
verbose = ["debug_ctap", "libtock_drivers/verbose_usb"]
|
verbose = ["debug_ctap", "libtock_drivers/verbose_usb"]
|
||||||
with_ctap1 = ["crypto/with_ctap1"]
|
with_ctap1 = ["opensk/with_ctap1"]
|
||||||
with_nfc = ["libtock_drivers/with_nfc"]
|
with_nfc = ["libtock_drivers/with_nfc"]
|
||||||
vendor_hid = ["libtock_drivers/vendor_hid"]
|
vendor_hid = ["opensk/vendor_hid"]
|
||||||
fuzz = ["arbitrary", "std"]
|
ed25519 = ["ed25519-compact", "opensk/ed25519"]
|
||||||
ed25519 = ["ed25519-compact"]
|
rust_crypto = ["opensk/rust_crypto"]
|
||||||
|
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
enum-iterator = "0.6.0"
|
enum-iterator = "0.6.0"
|
||||||
@@ -44,7 +52,7 @@ enum-iterator = "0.6.0"
|
|||||||
[build-dependencies]
|
[build-dependencies]
|
||||||
sk-cbor = { path = "libraries/cbor" }
|
sk-cbor = { path = "libraries/cbor" }
|
||||||
uuid = { version = "0.8", features = ["v4"] }
|
uuid = { version = "0.8", features = ["v4"] }
|
||||||
openssl = "0.10.36"
|
openssl = "0.10.55"
|
||||||
|
|
||||||
[profile.dev]
|
[profile.dev]
|
||||||
panic = "abort"
|
panic = "abort"
|
||||||
@@ -55,3 +63,8 @@ panic = "abort"
|
|||||||
lto = true # Link Time Optimization usually reduces size of binaries and static libraries
|
lto = true # Link Time Optimization usually reduces size of binaries and static libraries
|
||||||
opt-level = "z"
|
opt-level = "z"
|
||||||
codegen-units = 1
|
codegen-units = 1
|
||||||
|
|
||||||
|
[profile.release.package]
|
||||||
|
aes = { opt-level = 3 }
|
||||||
|
sha2 = { opt-level = 3 }
|
||||||
|
p256 = { opt-level = 3 }
|
||||||
|
|||||||
182
README.md
182
README.md
@@ -1,114 +1,118 @@
|
|||||||
# <img alt="OpenSK logo" src="docs/img/OpenSK.svg" width="200px">
|
# <img alt="OpenSK logo" src="docs/img/OpenSK.svg" width="200px">
|
||||||
|
|
||||||
|

|
||||||
|

|
||||||
|

|
||||||
|

|
||||||
|
[](https://coveralls.io/github/google/OpenSK?branch=develop)
|
||||||
|
|
||||||
|
*News:*
|
||||||
|
|
||||||
|
- 2023-08-24: [PQC paper reference](#Research)
|
||||||
|
|
||||||
## OpenSK
|
## OpenSK
|
||||||
|
|
||||||
This is an OpenSK fork that allows signing with a PQC Hybrid scheme. If you are looking for the original documentation, please check the
|
This repository contains a Rust implementation of a
|
||||||
[develop branch of its GitHub page](https://github.com/google/OpenSK/tree/develop).
|
[FIDO2](https://fidoalliance.org/fido2/) security key.
|
||||||
|
Security keys are external devices that can be used for signing in on websites.
|
||||||
|
You can see OpenSK in action in this
|
||||||
|
[video on YouTube](https://www.youtube.com/watch?v=klEozvpw0xg)!
|
||||||
|
|
||||||
|
We intend to bring a full open source experience to security keys, from
|
||||||
|
application to operating system. You can even 3D print your own open source
|
||||||
|
enclosure!
|
||||||
|
|
||||||
|
<img src="docs/img/enclosure.jpg" alt="OpenSK Enclosure" width="200"/>
|
||||||
|
|
||||||
|
You can run OpenSK as a [Tock OS](https://tockos.org) application, or use the
|
||||||
|
library to bring OpenSK to your own hardware.
|
||||||
|
|
||||||
|
You are viewing the branch for developers. New features are developed here.
|
||||||
|
Go to the default branch for a more stable version of OpenSK.
|
||||||
|
|
||||||
|
### FIDO2
|
||||||
|
|
||||||
|
OpenSK's version that implemented CTAP 2.0 was certified by the FIDO Alliance.
|
||||||
|
|
||||||
|
The develop branch tracks the latest release version of the
|
||||||
|
[CTAP specification](https://fidoalliance.org/specs/fido-v2.2-rd-20230321/fido-client-to-authenticator-protocol-v2.2-rd-20230321.html).
|
||||||
|
This branch is not FIDO certified.
|
||||||
|
OpenSK supports U2F, and non-discoverable credentials created with either
|
||||||
|
protocol are compatible with the other.
|
||||||
|
|
||||||
|
### :warning: Disclaimer
|
||||||
|
|
||||||
|
This project is **proof-of-concept and a research platform**. It is **NOT**
|
||||||
|
meant for a daily usage. This branch is under development, and therefore less
|
||||||
|
rigorously tested than the numbered branches.
|
||||||
|
|
||||||
|
We're still in the process of integrating the
|
||||||
|
[ARM® CryptoCell-310](https://developer.arm.com/ip-products/security-ip/cryptocell-300-family)
|
||||||
|
embedded in the
|
||||||
|
[Nordic nRF52840 chip](https://infocenter.nordicsemi.com/index.jsp?topic=%2Fps_nrf52840%2Fcryptocell.html)
|
||||||
|
to enable hardware-accelerated cryptography.
|
||||||
|
In the meantime, there are 2 options for cryptography implementations:
|
||||||
|
|
||||||
|
* Our own placeholder implementation. The code is research quality and doesn't
|
||||||
|
provide constant-time guarantees.
|
||||||
|
* The [RustCrypto](https://github.com/RustCrypto) interface. Deploy with
|
||||||
|
`--rust-crypto`. Note that our own ECC implementation is faster and has
|
||||||
|
smaller binary size, so not all boards support RustCrypto yet.
|
||||||
|
|
||||||
## Hardware
|
## Hardware
|
||||||
|
|
||||||
You will need a
|
You will need one the following supported boards:
|
||||||
[Nordic nRF52840-DK](https://www.nordicsemi.com/Software-and-Tools/Development-Kits/nRF52840-DK)
|
|
||||||
development kit.
|
* [Nordic nRF52840-DK](https://www.nordicsemi.com/Software-and-Tools/Development-Kits/nRF52840-DK)
|
||||||
|
development kit. This board is more convenient for development and debug
|
||||||
|
scenarios as the JTAG probe is already on the board.
|
||||||
|
* [Nordic nRF52840 Dongle](https://www.nordicsemi.com/Software-and-tools/Development-Kits/nRF52840-Dongle)
|
||||||
|
to have a more practical form factor.
|
||||||
|
* [Makerdiary nRF52840-MDK USB dongle](https://wiki.makerdiary.com/nrf52840-mdk/).
|
||||||
|
* [Feitian OpenSK dongle](https://feitiantech.github.io/OpenSK_USB/).
|
||||||
|
|
||||||
## Installation
|
## Installation
|
||||||
|
|
||||||
To install OpenSK,
|
To install OpenSK,
|
||||||
|
|
||||||
1. follow the [general setup steps](docs/install.md),
|
1. follow the [general setup steps](docs/install.md),
|
||||||
1. then continue with the instructions for your specific hardware:
|
1. then continue with the instructions for your specific hardware:
|
||||||
[Nordic nRF52840-DK](docs/boards/nrf52840dk.md)
|
* [Nordic nRF52840-DK](docs/boards/nrf52840dk.md)
|
||||||
|
* [Nordic nRF52840 Dongle](docs/boards/nrf52840_dongle.md)
|
||||||
|
* [Makerdiary nRF52840-MDK USB dongle](docs/boards/nrf52840_mdk.md)
|
||||||
|
* [Feitian OpenSK dongle](docs/boards/nrf52840_feitian.md)
|
||||||
|
|
||||||
## PQC Experiments
|
To test whether the installation was successful, visit a
|
||||||
|
[demo website](https://webauthn.io/) and try to register and login.
|
||||||
|
Please check our [Troubleshooting and Debugging](docs/debugging.md) section if you
|
||||||
|
have problems with the installation process or during development. To find out what
|
||||||
|
else you can do with your OpenSK, see [Customization](docs/customization.md).
|
||||||
|
|
||||||
### Modes
|
## Research
|
||||||
|
|
||||||
The Dilithium mode is set at compile time. If you want to perform experiments for different modes,
|
We implemented post-quantum cryptography on OpenSK. The code is released under
|
||||||
you will need to recompile. The mode is a feature, defined in
|
the [hybrid-pqc tag](https://github.com/google/OpenSK/releases/tag/hybrid-pqc).
|
||||||
`third_party/dilithium/Cargo.toml`. By default, it is set to
|
Our [paper](https://eprint.iacr.org/2022/1225) was published in the ACNS
|
||||||
`default = [ "dilithium5", "optimize_stack" ]`. You can change the default mode by either changing
|
Secure Cryptographic Implementation workshop 2023 and won the best paper award.
|
||||||
the number 5 to 2 or 3. Or you remove the feature for stack optimizations, e.g.
|
|
||||||
`default = [ "dilithium2" ]`.
|
|
||||||
|
|
||||||
Note that some benchmarks will not run in all modes without stack optimizations. You can try to
|
<details>
|
||||||
play with the stack size in these cases. As an example, stack painting for speed mode Dilithium2
|
<summary>Bibtex reference</summary>
|
||||||
works if you apply the following changes:
|
|
||||||
|
|
||||||
* `APP_HEAP_SIZE = 16384` in `deploy.py`
|
|
||||||
* `libtock_core::stack_size! {0x1A000}` in `examples/measure_stack.rs`
|
|
||||||
* `STACK_SIZE = 106496;` in `nrf52840_layout.ld`
|
|
||||||
* Change the app break from `70 * 1024` to `104 * 1024` in `patches/tock/07-app-break-fix.patch`.
|
|
||||||
|
|
||||||
For your convenience, you can also simply try:
|
|
||||||
|
|
||||||
```
|
```
|
||||||
git apply increase_stack.patch
|
@InProceedings{Ghinea2023hybrid,
|
||||||
|
author= {Diana Ghinea and Fabian Kaczmarczyck and Jennifer Pullman and Julien Cretin and Rafael Misoczki and Stefan Kölbl and Luca Invernizzi and Elie Bursztein and Jean-Michel Picod},
|
||||||
|
title= {{Hybrid Post-Quantum Signatures in Hardware Security Keys}},
|
||||||
|
booktitle= {{4th ACNS Workshop on Secure Cryptographic Implementation, Kyoto, Japan}},
|
||||||
|
month= {June},
|
||||||
|
year= {2023},
|
||||||
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
### Compiler flags
|
</details>
|
||||||
|
|
||||||
To trade binary size for speed, you can play with `[profile.release]` in `Cargo.toml`.
|
## Contributing
|
||||||
For example, try a different compiler optimization level:
|
|
||||||
|
|
||||||
```
|
See [Contributing.md](docs/contributing.md).
|
||||||
opt-level = 3
|
|
||||||
```
|
|
||||||
|
|
||||||
### Debug output
|
## Reporting a Vulnerability
|
||||||
|
|
||||||
Only the CTAP commands tests are measured end to end on the host. All other experiments are
|
|
||||||
measured on the embedded device itself and output over RTT. You can either use a client to print
|
|
||||||
results by running the following commands in different terminals:
|
|
||||||
|
|
||||||
```
|
|
||||||
JLinkExe -device nrf52 -if swd -speed 1000 -autoconnect 1
|
|
||||||
JLinkRTTClient
|
|
||||||
```
|
|
||||||
|
|
||||||
Or you directly output all messages to a file:
|
|
||||||
|
|
||||||
```
|
|
||||||
JLinkRTTLogger -device NRF52840_XXAA -if swd -speed 1000 -RTTchannel 0
|
|
||||||
```
|
|
||||||
|
|
||||||
### Perform Experiments
|
|
||||||
|
|
||||||
The paper contains the following experiments:
|
|
||||||
|
|
||||||
#### Crypto benchmarks
|
|
||||||
|
|
||||||
Deploy the `crypto_bench` example and read the debug output with one of the methods above:
|
|
||||||
|
|
||||||
```
|
|
||||||
./deploy.py --board=nrf52840dk_opensk --crypto_bench
|
|
||||||
```
|
|
||||||
|
|
||||||
#### CTAP benchmarks
|
|
||||||
|
|
||||||
To measure the speed of FIDO commands, run:
|
|
||||||
|
|
||||||
```
|
|
||||||
python benchmarks.py --runs=2000
|
|
||||||
```
|
|
||||||
|
|
||||||
Aggregate results will be printed, and the raw data is written to `make_durations.txt` and
|
|
||||||
`get_durations.txt`.
|
|
||||||
|
|
||||||
|
|
||||||
#### Stack painting
|
|
||||||
|
|
||||||
Deploy the `measure_stack` example and read the debug output with one of the methods above:
|
|
||||||
|
|
||||||
```
|
|
||||||
./deploy.py --board=nrf52840dk_opensk --measure_stack
|
|
||||||
```
|
|
||||||
|
|
||||||
#### x86 benchmarks
|
|
||||||
|
|
||||||
You don't need your embedded hardware for those, run:
|
|
||||||
|
|
||||||
```
|
|
||||||
cd third_party/dilithium/
|
|
||||||
cargo bench --features std
|
|
||||||
```
|
|
||||||
|
|
||||||
|
See [SECURITY.md](SECURITY.md).
|
||||||
|
|||||||
167
benchmarks.py
167
benchmarks.py
@@ -1,167 +0,0 @@
|
|||||||
#!/usr/bin/env python3
|
|
||||||
# Copyright 2022 Google LLC
|
|
||||||
#
|
|
||||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
# you may not use this file except in compliance with the License.
|
|
||||||
# You may obtain a copy of the License at
|
|
||||||
#
|
|
||||||
# http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
#
|
|
||||||
# Unless required by applicable law or agreed to in writing, software
|
|
||||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
# See the License for the specific language governing permissions and
|
|
||||||
# limitations under the License.
|
|
||||||
# Lint as: python3
|
|
||||||
"""Script to benchmark CTAP commands using Dilithium Hybrid signatures."""
|
|
||||||
|
|
||||||
from __future__ import absolute_import
|
|
||||||
from __future__ import division
|
|
||||||
from __future__ import print_function
|
|
||||||
|
|
||||||
import argparse
|
|
||||||
import datetime
|
|
||||||
from subprocess import DEVNULL, STDOUT, check_call
|
|
||||||
import sys
|
|
||||||
from time import sleep
|
|
||||||
from typing import Any
|
|
||||||
import uuid
|
|
||||||
|
|
||||||
import colorama
|
|
||||||
from tqdm.auto import tqdm
|
|
||||||
|
|
||||||
from fido2 import ctap
|
|
||||||
from fido2.webauthn import PublicKeyCredentialRpEntity, PublicKeyCredentialUserEntity, PublicKeyCredentialParameters
|
|
||||||
from fido2 import hid
|
|
||||||
from tools.configure import fatal, info, get_opensk_devices
|
|
||||||
|
|
||||||
ES256_ALGORITHM = PublicKeyCredentialParameters("public-key", -7)
|
|
||||||
HYBRID_ALGORITHM = PublicKeyCredentialParameters("public-key", -65537)
|
|
||||||
|
|
||||||
|
|
||||||
def error(message: str):
|
|
||||||
tqdm.write(message)
|
|
||||||
|
|
||||||
|
|
||||||
def check_info(authenticator: Any):
|
|
||||||
"""Checks if the assumed upgrade info matches the authenticator's."""
|
|
||||||
try:
|
|
||||||
info("Reading info...")
|
|
||||||
if HYBRID_ALGORITHM not in authenticator.info.algorithms:
|
|
||||||
fatal("The device does not support hybrid signatures.")
|
|
||||||
except ctap.CtapError as ex:
|
|
||||||
error(f"Failed to read OpenSK info (error: {ex}")
|
|
||||||
|
|
||||||
|
|
||||||
def f_args(*params):
|
|
||||||
"""Constructs a dict from a list of arguments for sending a CBOR command.
|
|
||||||
None elements will be omitted.
|
|
||||||
:param params: Arguments, in order, to add to the command.
|
|
||||||
:return: The input parameters as a dict.
|
|
||||||
"""
|
|
||||||
return dict((i, v) for i, v in enumerate(params, 1) if v is not None)
|
|
||||||
|
|
||||||
|
|
||||||
def compute_stats(elapsed):
|
|
||||||
n = len(elapsed)
|
|
||||||
mean = sum(elapsed) / n
|
|
||||||
variance = sum((x - mean)**2 for x in elapsed) / n
|
|
||||||
std_dev = variance**0.5
|
|
||||||
return (mean, std_dev)
|
|
||||||
|
|
||||||
|
|
||||||
def get_authenticator():
|
|
||||||
devices = None
|
|
||||||
while not devices:
|
|
||||||
try:
|
|
||||||
devices = get_opensk_devices(False)
|
|
||||||
except Exception as e: # pylint: disable=broad-except
|
|
||||||
error(str(e))
|
|
||||||
check_call(["nrfjprog", "--reset", "--family", "NRF52"],
|
|
||||||
stdout=DEVNULL,
|
|
||||||
stderr=STDOUT)
|
|
||||||
sleep(0.1)
|
|
||||||
return devices[0]
|
|
||||||
|
|
||||||
|
|
||||||
def main(args):
|
|
||||||
colorama.init()
|
|
||||||
|
|
||||||
authenticator = get_authenticator()
|
|
||||||
# If the device supports it, wink to show which device we use.
|
|
||||||
if authenticator.device.capabilities & hid.CAPABILITY.WINK:
|
|
||||||
authenticator.device.wink()
|
|
||||||
aaguid = uuid.UUID(bytes=authenticator.get_info().aaguid)
|
|
||||||
check_info(authenticator)
|
|
||||||
info(f"Testing OpenSK device AAGUID {aaguid} ({authenticator.device}).")
|
|
||||||
|
|
||||||
make_durations = []
|
|
||||||
get_durations = []
|
|
||||||
|
|
||||||
for _ in tqdm(range(args.runs), file=sys.stdout):
|
|
||||||
authenticator = get_authenticator()
|
|
||||||
try:
|
|
||||||
start = datetime.datetime.now()
|
|
||||||
result = authenticator.make_credential(
|
|
||||||
client_data_hash=bytes(32),
|
|
||||||
rp=PublicKeyCredentialRpEntity(id="example.com", name="Example"),
|
|
||||||
user=PublicKeyCredentialUserEntity(id=b"diana", name="Diana"),
|
|
||||||
key_params=[HYBRID_ALGORITHM],
|
|
||||||
)
|
|
||||||
end = datetime.datetime.now()
|
|
||||||
make_delta = (end - start).total_seconds() * 1000.0
|
|
||||||
make_durations.append(make_delta)
|
|
||||||
|
|
||||||
credential_data = result.auth_data.credential_data
|
|
||||||
credential_id_length = 256 * credential_data[16] + credential_data[17]
|
|
||||||
credential_id = credential_data[18:18 + credential_id_length]
|
|
||||||
allow_list = [{"type": "public-key", "id": credential_id}]
|
|
||||||
|
|
||||||
start = datetime.datetime.now()
|
|
||||||
_ = authenticator.get_assertion(
|
|
||||||
rp_id="example.com",
|
|
||||||
client_data_hash=bytes(32),
|
|
||||||
allow_list=allow_list,
|
|
||||||
)
|
|
||||||
end = datetime.datetime.now()
|
|
||||||
get_delta = (end - start).total_seconds() * 1000.0
|
|
||||||
get_durations.append(get_delta)
|
|
||||||
|
|
||||||
with open("make_durations.txt", "a", encoding="utf-8") as file_make:
|
|
||||||
file_make.write(str(make_delta) + ",\n")
|
|
||||||
with open("get_durations.txt", "a", encoding="utf-8") as file_get:
|
|
||||||
file_get.write(str(get_delta) + ",\n")
|
|
||||||
|
|
||||||
except ctap.CtapError as ex:
|
|
||||||
message = "Failed to make a hybrid signature with OpenSK"
|
|
||||||
if ex.code.value == ctap.CtapError.ERR.INVALID_COMMAND:
|
|
||||||
error(f"{message} (unsupported command).")
|
|
||||||
elif ex.code.value == ctap.CtapError.ERR.INVALID_PARAMETER:
|
|
||||||
error(f"{message} (invalid parameter, maybe a wrong byte array size?).")
|
|
||||||
elif ex.code.value == 0xF2: # VENDOR_INTERNAL_ERROR
|
|
||||||
error(f"{message} (internal conditions not met).")
|
|
||||||
elif ex.code.value == 0xF3: # VENDOR_HARDWARE_FAILURE
|
|
||||||
error(f"{message} (internal hardware error).")
|
|
||||||
else:
|
|
||||||
error(f"{message} (unexpected error: {ex})")
|
|
||||||
except Exception as e: # pylint: disable=broad-except
|
|
||||||
error(str(e))
|
|
||||||
|
|
||||||
info(f"Successful operations: {len(make_durations)} and {len(get_durations)}")
|
|
||||||
info("\nMake Credential benchmark:")
|
|
||||||
(mean, std_dev) = compute_stats(make_durations)
|
|
||||||
info(f"Average: {mean} ms/iter (standard deviation: {std_dev} ms/iter)")
|
|
||||||
info("\nGet Assertion benchmark:")
|
|
||||||
(mean, std_dev) = compute_stats(get_durations)
|
|
||||||
info(f"Average: {mean} ms/iter (standard deviation: {std_dev} ms/iter)")
|
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
|
||||||
parser = argparse.ArgumentParser()
|
|
||||||
parser.add_argument(
|
|
||||||
"--runs",
|
|
||||||
type=int,
|
|
||||||
default=1000,
|
|
||||||
help=("How many iterations to use."),
|
|
||||||
)
|
|
||||||
main(parser.parse_args())
|
|
||||||
@@ -7,8 +7,7 @@ use kernel::hil::led;
|
|||||||
use kernel::hil::uart::{self, Configure};
|
use kernel::hil::uart::{self, Configure};
|
||||||
use nrf52840::gpio::Pin;
|
use nrf52840::gpio::Pin;
|
||||||
|
|
||||||
use crate::CHIP;
|
use crate::{CHIP, PROCESSES, PROCESS_PRINTER};
|
||||||
use crate::PROCESSES;
|
|
||||||
|
|
||||||
struct Writer {
|
struct Writer {
|
||||||
initialized: bool,
|
initialized: bool,
|
||||||
@@ -31,7 +30,7 @@ impl IoWrite for Writer {
|
|||||||
let uart = nrf52840::uart::Uarte::new();
|
let uart = nrf52840::uart::Uarte::new();
|
||||||
if !self.initialized {
|
if !self.initialized {
|
||||||
self.initialized = true;
|
self.initialized = true;
|
||||||
uart.configure(uart::Parameters {
|
let _ = uart.configure(uart::Parameters {
|
||||||
baud_rate: 115200,
|
baud_rate: 115200,
|
||||||
stop_bits: uart::StopBits::One,
|
stop_bits: uart::StopBits::One,
|
||||||
parity: uart::Parity::None,
|
parity: uart::Parity::None,
|
||||||
@@ -64,5 +63,6 @@ pub unsafe extern "C" fn panic_fmt(pi: &PanicInfo) -> ! {
|
|||||||
&cortexm4::support::nop,
|
&cortexm4::support::nop,
|
||||||
&PROCESSES,
|
&PROCESSES,
|
||||||
&CHIP,
|
&CHIP,
|
||||||
|
&PROCESS_PRINTER,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,15 +7,18 @@
|
|||||||
// Disable this attribute when documenting, as a workaround for
|
// Disable this attribute when documenting, as a workaround for
|
||||||
// https://github.com/rust-lang/rust/issues/62184.
|
// https://github.com/rust-lang/rust/issues/62184.
|
||||||
#![cfg_attr(not(doc), no_main)]
|
#![cfg_attr(not(doc), no_main)]
|
||||||
#![feature(const_in_array_repeat_expressions)]
|
|
||||||
#![deny(missing_docs)]
|
#![deny(missing_docs)]
|
||||||
|
|
||||||
use kernel::common::dynamic_deferred_call::{DynamicDeferredCall, DynamicDeferredCallClientState};
|
use capsules::virtual_alarm::VirtualMuxAlarm;
|
||||||
use kernel::component::Component;
|
use kernel::component::Component;
|
||||||
|
use kernel::dynamic_deferred_call::{DynamicDeferredCall, DynamicDeferredCallClientState};
|
||||||
use kernel::hil::led::LedLow;
|
use kernel::hil::led::LedLow;
|
||||||
use kernel::hil::time::Counter;
|
use kernel::hil::time::Counter;
|
||||||
|
use kernel::platform::{KernelResources, SyscallDriverLookup, SyscallFilter};
|
||||||
|
use kernel::scheduler::round_robin::RoundRobinSched;
|
||||||
#[allow(unused_imports)]
|
#[allow(unused_imports)]
|
||||||
use kernel::{capabilities, create_capability, debug, debug_gpio, debug_verbose, static_init};
|
use kernel::{capabilities, create_capability, debug, debug_gpio, debug_verbose, static_init};
|
||||||
|
use kernel::{StorageLocation, StorageType};
|
||||||
use nrf52840::gpio::Pin;
|
use nrf52840::gpio::Pin;
|
||||||
use nrf52840::interrupt_service::Nrf52840DefaultPeripherals;
|
use nrf52840::interrupt_service::Nrf52840DefaultPeripherals;
|
||||||
use nrf52_components::{self, UartChannel, UartPins};
|
use nrf52_components::{self, UartChannel, UartPins};
|
||||||
@@ -52,34 +55,43 @@ static STRINGS: &'static [&'static str] = &[
|
|||||||
"OpenSK",
|
"OpenSK",
|
||||||
// Serial number
|
// Serial number
|
||||||
"v1.0",
|
"v1.0",
|
||||||
|
// Interface description + main HID string
|
||||||
|
"FIDO2",
|
||||||
|
// vendor HID string
|
||||||
|
"Vendor HID",
|
||||||
];
|
];
|
||||||
|
|
||||||
// State for loading and holding applications.
|
// State for loading and holding applications.
|
||||||
// How should the kernel respond when a process faults.
|
// How should the kernel respond when a process faults.
|
||||||
const FAULT_RESPONSE: kernel::procs::FaultResponse = kernel::procs::FaultResponse::Panic;
|
const FAULT_RESPONSE: kernel::process::PanicFaultPolicy = kernel::process::PanicFaultPolicy {};
|
||||||
|
|
||||||
// Number of concurrent processes this platform supports.
|
// Number of concurrent processes this platform supports.
|
||||||
const NUM_PROCS: usize = 8;
|
const NUM_PROCS: usize = 8;
|
||||||
|
|
||||||
static mut PROCESSES: [Option<&'static dyn kernel::procs::ProcessType>; NUM_PROCS] =
|
static mut PROCESSES: [Option<&'static dyn kernel::process::Process>; NUM_PROCS] =
|
||||||
[None; NUM_PROCS];
|
[None; NUM_PROCS];
|
||||||
|
|
||||||
static mut STORAGE_LOCATIONS: [kernel::StorageLocation; 2] = [
|
static mut STORAGE_LOCATIONS: [StorageLocation; 2] = [
|
||||||
// We implement NUM_PAGES = 20 as 16 + 4 to satisfy the MPU.
|
// We implement NUM_PAGES = 20 as 16 + 4 to satisfy the MPU.
|
||||||
kernel::StorageLocation {
|
StorageLocation {
|
||||||
address: 0xC0000,
|
address: 0xC0000,
|
||||||
size: 0x10000, // 16 pages
|
size: 0x10000, // 16 pages
|
||||||
storage_type: kernel::StorageType::Store,
|
storage_type: StorageType::Store,
|
||||||
},
|
},
|
||||||
kernel::StorageLocation {
|
StorageLocation {
|
||||||
address: 0xD0000,
|
address: 0xD0000,
|
||||||
size: 0x4000, // 4 pages
|
size: 0x4000, // 4 pages
|
||||||
storage_type: kernel::StorageType::Store,
|
storage_type: StorageType::Store,
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
// Static reference to chip for panic dumps
|
// Static reference to chip for panic dumps
|
||||||
static mut CHIP: Option<&'static nrf52840::chip::NRF52<Nrf52840DefaultPeripherals>> = None;
|
static mut CHIP: Option<&'static nrf52840::chip::NRF52<Nrf52840DefaultPeripherals>> = None;
|
||||||
|
// Static reference to process printer for panic dumps
|
||||||
|
static mut PROCESS_PRINTER: Option<&'static kernel::process::ProcessPrinterText> = None;
|
||||||
|
|
||||||
|
/// Flash buffer for the custom nvmc driver
|
||||||
|
static mut APP_FLASH_BUFFER: [u8; 0x1000] = [0; 0x1000];
|
||||||
|
|
||||||
/// Dummy buffer that causes the linker to reserve enough space for the stack.
|
/// Dummy buffer that causes the linker to reserve enough space for the stack.
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
@@ -91,6 +103,7 @@ pub struct Platform {
|
|||||||
button: &'static capsules::button::Button<'static, nrf52840::gpio::GPIOPin<'static>>,
|
button: &'static capsules::button::Button<'static, nrf52840::gpio::GPIOPin<'static>>,
|
||||||
pconsole: &'static capsules::process_console::ProcessConsole<
|
pconsole: &'static capsules::process_console::ProcessConsole<
|
||||||
'static,
|
'static,
|
||||||
|
VirtualMuxAlarm<'static, nrf52840::rtc::Rtc<'static>>,
|
||||||
components::process_console::Capability,
|
components::process_console::Capability,
|
||||||
>,
|
>,
|
||||||
console: &'static capsules::console::Console<'static>,
|
console: &'static capsules::console::Console<'static>,
|
||||||
@@ -98,9 +111,10 @@ pub struct Platform {
|
|||||||
led: &'static capsules::led::LedDriver<
|
led: &'static capsules::led::LedDriver<
|
||||||
'static,
|
'static,
|
||||||
LedLow<'static, nrf52840::gpio::GPIOPin<'static>>,
|
LedLow<'static, nrf52840::gpio::GPIOPin<'static>>,
|
||||||
|
4,
|
||||||
>,
|
>,
|
||||||
rng: &'static capsules::rng::RngDriver<'static>,
|
rng: &'static capsules::rng::RngDriver<'static>,
|
||||||
ipc: kernel::ipc::IPC<NUM_PROCS>,
|
ipc: kernel::ipc::IPC<{ NUM_PROCS as u8 }>,
|
||||||
analog_comparator: &'static capsules::analog_comparator::AnalogComparator<
|
analog_comparator: &'static capsules::analog_comparator::AnalogComparator<
|
||||||
'static,
|
'static,
|
||||||
nrf52840::acomp::Comparator<'static>,
|
nrf52840::acomp::Comparator<'static>,
|
||||||
@@ -109,19 +123,20 @@ pub struct Platform {
|
|||||||
'static,
|
'static,
|
||||||
capsules::virtual_alarm::VirtualMuxAlarm<'static, nrf52840::rtc::Rtc<'static>>,
|
capsules::virtual_alarm::VirtualMuxAlarm<'static, nrf52840::rtc::Rtc<'static>>,
|
||||||
>,
|
>,
|
||||||
|
scheduler: &'static RoundRobinSched<'static>,
|
||||||
|
systick: cortexm4::systick::SysTick,
|
||||||
nvmc: &'static nrf52840::nvmc::SyscallDriver,
|
nvmc: &'static nrf52840::nvmc::SyscallDriver,
|
||||||
usb: &'static capsules::usb::usb_ctap::CtapUsbSyscallDriver<
|
usb: &'static capsules::usb::usb_ctap::CtapUsbSyscallDriver<
|
||||||
'static,
|
'static,
|
||||||
'static,
|
'static,
|
||||||
nrf52840::usbd::Usbd<'static>,
|
nrf52840::usbd::Usbd<'static>,
|
||||||
>,
|
>,
|
||||||
crp: &'static capsules::firmware_protection::FirmwareProtection<nrf52840::uicr::Uicr>,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl kernel::Platform for Platform {
|
impl SyscallDriverLookup for Platform {
|
||||||
fn with_driver<F, R>(&self, driver_num: usize, f: F) -> R
|
fn with_driver<F, R>(&self, driver_num: usize, f: F) -> R
|
||||||
where
|
where
|
||||||
F: FnOnce(Option<&dyn kernel::Driver>) -> R,
|
F: FnOnce(Option<&dyn kernel::syscall::SyscallDriver>) -> R,
|
||||||
{
|
{
|
||||||
match driver_num {
|
match driver_num {
|
||||||
capsules::console::DRIVER_NUM => f(Some(self.console)),
|
capsules::console::DRIVER_NUM => f(Some(self.console)),
|
||||||
@@ -133,45 +148,88 @@ impl kernel::Platform for Platform {
|
|||||||
capsules::analog_comparator::DRIVER_NUM => f(Some(self.analog_comparator)),
|
capsules::analog_comparator::DRIVER_NUM => f(Some(self.analog_comparator)),
|
||||||
nrf52840::nvmc::DRIVER_NUM => f(Some(self.nvmc)),
|
nrf52840::nvmc::DRIVER_NUM => f(Some(self.nvmc)),
|
||||||
capsules::usb::usb_ctap::DRIVER_NUM => f(Some(self.usb)),
|
capsules::usb::usb_ctap::DRIVER_NUM => f(Some(self.usb)),
|
||||||
capsules::firmware_protection::DRIVER_NUM => f(Some(self.crp)),
|
|
||||||
kernel::ipc::DRIVER_NUM => f(Some(&self.ipc)),
|
kernel::ipc::DRIVER_NUM => f(Some(&self.ipc)),
|
||||||
_ => f(None),
|
_ => f(None),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl SyscallFilter for Platform {
|
||||||
fn filter_syscall(
|
fn filter_syscall(
|
||||||
&self,
|
&self,
|
||||||
process: &dyn kernel::procs::ProcessType,
|
process: &dyn kernel::process::Process,
|
||||||
syscall: &kernel::syscall::Syscall,
|
syscall: &kernel::syscall::Syscall,
|
||||||
) -> Result<(), kernel::ReturnCode> {
|
) -> Result<(), kernel::errorcode::ErrorCode> {
|
||||||
use kernel::syscall::Syscall;
|
use kernel::syscall::Syscall;
|
||||||
match *syscall {
|
match *syscall {
|
||||||
Syscall::COMMAND {
|
Syscall::Command {
|
||||||
driver_number: nrf52840::nvmc::DRIVER_NUM,
|
driver_number: nrf52840::nvmc::DRIVER_NUM,
|
||||||
subdriver_number: cmd,
|
subdriver_number: cmd,
|
||||||
arg0: ptr,
|
arg0: ptr,
|
||||||
arg1: len,
|
arg1: len,
|
||||||
} if (cmd == 2 || cmd == 3) && !process.fits_in_storage_location(ptr, len) => {
|
} if (cmd == 2 || cmd == 3) && !process.fits_in_storage_location(ptr, len) => {
|
||||||
Err(kernel::ReturnCode::EINVAL)
|
Err(kernel::ErrorCode::INVAL)
|
||||||
}
|
}
|
||||||
_ => Ok(()),
|
_ => Ok(()),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Entry point in the vector table called on hard reset.
|
impl KernelResources<nrf52840::chip::NRF52<'static, Nrf52840DefaultPeripherals<'static>>>
|
||||||
#[no_mangle]
|
for Platform
|
||||||
pub unsafe fn reset_handler() {
|
{
|
||||||
// Loads relocations and clears BSS
|
type SyscallDriverLookup = Self;
|
||||||
nrf52840::init();
|
type SyscallFilter = Self;
|
||||||
|
type ProcessFault = ();
|
||||||
|
type Scheduler = RoundRobinSched<'static>;
|
||||||
|
type SchedulerTimer = cortexm4::systick::SysTick;
|
||||||
|
type WatchDog = ();
|
||||||
|
type ContextSwitchCallback = ();
|
||||||
|
|
||||||
let ppi = static_init!(nrf52840::ppi::Ppi, nrf52840::ppi::Ppi::new());
|
fn syscall_driver_lookup(&self) -> &Self::SyscallDriverLookup {
|
||||||
|
&self
|
||||||
|
}
|
||||||
|
fn syscall_filter(&self) -> &Self::SyscallFilter {
|
||||||
|
&self
|
||||||
|
}
|
||||||
|
fn process_fault(&self) -> &Self::ProcessFault {
|
||||||
|
&()
|
||||||
|
}
|
||||||
|
fn scheduler(&self) -> &Self::Scheduler {
|
||||||
|
self.scheduler
|
||||||
|
}
|
||||||
|
fn scheduler_timer(&self) -> &Self::SchedulerTimer {
|
||||||
|
&self.systick
|
||||||
|
}
|
||||||
|
fn watchdog(&self) -> &Self::WatchDog {
|
||||||
|
&()
|
||||||
|
}
|
||||||
|
fn context_switch_callback(&self) -> &Self::ContextSwitchCallback {
|
||||||
|
&()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// This is in a separate, inline(never) function so that its stack frame is
|
||||||
|
/// removed when this function returns. Otherwise, the stack space used for
|
||||||
|
/// these static_inits is wasted.
|
||||||
|
#[inline(never)]
|
||||||
|
unsafe fn get_peripherals() -> &'static mut Nrf52840DefaultPeripherals<'static> {
|
||||||
// Initialize chip peripheral drivers
|
// Initialize chip peripheral drivers
|
||||||
let nrf52840_peripherals = static_init!(
|
let nrf52840_peripherals = static_init!(
|
||||||
Nrf52840DefaultPeripherals,
|
Nrf52840DefaultPeripherals,
|
||||||
Nrf52840DefaultPeripherals::new(ppi)
|
Nrf52840DefaultPeripherals::new()
|
||||||
);
|
);
|
||||||
|
|
||||||
|
nrf52840_peripherals
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Main function called after RAM initialized.
|
||||||
|
#[no_mangle]
|
||||||
|
pub unsafe fn main() {
|
||||||
|
nrf52840::init();
|
||||||
|
|
||||||
|
let nrf52840_peripherals = get_peripherals();
|
||||||
|
|
||||||
// set up circular peripheral dependencies
|
// set up circular peripheral dependencies
|
||||||
nrf52840_peripherals.init();
|
nrf52840_peripherals.init();
|
||||||
let base_peripherals = &nrf52840_peripherals.nrf52;
|
let base_peripherals = &nrf52840_peripherals.nrf52;
|
||||||
@@ -184,6 +242,7 @@ pub unsafe fn reset_handler() {
|
|||||||
// GPIOs
|
// GPIOs
|
||||||
let gpio = components::gpio::GpioComponent::new(
|
let gpio = components::gpio::GpioComponent::new(
|
||||||
board_kernel,
|
board_kernel,
|
||||||
|
capsules::gpio::DRIVER_NUM,
|
||||||
components::gpio_component_helper!(
|
components::gpio_component_helper!(
|
||||||
nrf52840::gpio::GPIOPin,
|
nrf52840::gpio::GPIOPin,
|
||||||
// left side of the USB plug
|
// left side of the USB plug
|
||||||
@@ -219,6 +278,7 @@ pub unsafe fn reset_handler() {
|
|||||||
|
|
||||||
let button = components::button::ButtonComponent::new(
|
let button = components::button::ButtonComponent::new(
|
||||||
board_kernel,
|
board_kernel,
|
||||||
|
capsules::button::DRIVER_NUM,
|
||||||
components::button_component_helper!(
|
components::button_component_helper!(
|
||||||
nrf52840::gpio::GPIOPin,
|
nrf52840::gpio::GPIOPin,
|
||||||
(
|
(
|
||||||
@@ -230,15 +290,12 @@ pub unsafe fn reset_handler() {
|
|||||||
)
|
)
|
||||||
.finalize(components::button_component_buf!(nrf52840::gpio::GPIOPin));
|
.finalize(components::button_component_buf!(nrf52840::gpio::GPIOPin));
|
||||||
|
|
||||||
let led = components::led::LedsComponent::new(components::led_component_helper!(
|
let led = components::led::LedsComponent::new().finalize(components::led_component_helper!(
|
||||||
LedLow<'static, nrf52840::gpio::GPIOPin>,
|
LedLow<'static, nrf52840::gpio::GPIOPin>,
|
||||||
LedLow::new(&nrf52840_peripherals.gpio_port[LED1_PIN]),
|
LedLow::new(&nrf52840_peripherals.gpio_port[LED1_PIN]),
|
||||||
LedLow::new(&nrf52840_peripherals.gpio_port[LED2_R_PIN]),
|
LedLow::new(&nrf52840_peripherals.gpio_port[LED2_R_PIN]),
|
||||||
LedLow::new(&nrf52840_peripherals.gpio_port[LED2_G_PIN]),
|
LedLow::new(&nrf52840_peripherals.gpio_port[LED2_G_PIN]),
|
||||||
LedLow::new(&nrf52840_peripherals.gpio_port[LED2_B_PIN]),
|
LedLow::new(&nrf52840_peripherals.gpio_port[LED2_B_PIN]),
|
||||||
))
|
|
||||||
.finalize(components::led_component_buf!(
|
|
||||||
LedLow<'static, nrf52840::gpio::GPIOPin>
|
|
||||||
));
|
));
|
||||||
|
|
||||||
let chip = static_init!(
|
let chip = static_init!(
|
||||||
@@ -272,10 +329,14 @@ pub unsafe fn reset_handler() {
|
|||||||
);
|
);
|
||||||
|
|
||||||
let rtc = &base_peripherals.rtc;
|
let rtc = &base_peripherals.rtc;
|
||||||
rtc.start();
|
let _ = rtc.start();
|
||||||
let mux_alarm = components::alarm::AlarmMuxComponent::new(rtc)
|
let mux_alarm = components::alarm::AlarmMuxComponent::new(rtc)
|
||||||
.finalize(components::alarm_mux_component_helper!(nrf52840::rtc::Rtc));
|
.finalize(components::alarm_mux_component_helper!(nrf52840::rtc::Rtc));
|
||||||
let alarm = components::alarm::AlarmDriverComponent::new(board_kernel, mux_alarm)
|
let alarm = components::alarm::AlarmDriverComponent::new(
|
||||||
|
board_kernel,
|
||||||
|
capsules::alarm::DRIVER_NUM,
|
||||||
|
mux_alarm,
|
||||||
|
)
|
||||||
.finalize(components::alarm_component_helper!(nrf52840::rtc::Rtc));
|
.finalize(components::alarm_component_helper!(nrf52840::rtc::Rtc));
|
||||||
let uart_channel = UartChannel::Pins(UartPins::new(UART_RTS, UART_TXD, UART_CTS, UART_RXD));
|
let uart_channel = UartChannel::Pins(UartPins::new(UART_RTS, UART_TXD, UART_CTS, UART_RXD));
|
||||||
let channel = nrf52_components::UartChannelComponent::new(
|
let channel = nrf52_components::UartChannelComponent::new(
|
||||||
@@ -293,21 +354,41 @@ pub unsafe fn reset_handler() {
|
|||||||
);
|
);
|
||||||
DynamicDeferredCall::set_global_instance(dynamic_deferred_caller);
|
DynamicDeferredCall::set_global_instance(dynamic_deferred_caller);
|
||||||
|
|
||||||
|
let process_printer =
|
||||||
|
components::process_printer::ProcessPrinterTextComponent::new().finalize(());
|
||||||
|
PROCESS_PRINTER = Some(process_printer);
|
||||||
|
|
||||||
// Create a shared UART channel for the console and for kernel debug.
|
// Create a shared UART channel for the console and for kernel debug.
|
||||||
let uart_mux =
|
let uart_mux =
|
||||||
components::console::UartMuxComponent::new(channel, 115200, dynamic_deferred_caller)
|
components::console::UartMuxComponent::new(channel, 115200, dynamic_deferred_caller)
|
||||||
.finalize(());
|
.finalize(());
|
||||||
|
|
||||||
let pconsole =
|
let pconsole = components::process_console::ProcessConsoleComponent::new(
|
||||||
components::process_console::ProcessConsoleComponent::new(board_kernel, uart_mux)
|
board_kernel,
|
||||||
.finalize(());
|
uart_mux,
|
||||||
|
mux_alarm,
|
||||||
|
process_printer,
|
||||||
|
)
|
||||||
|
.finalize(components::process_console_component_helper!(
|
||||||
|
nrf52840::rtc::Rtc<'static>
|
||||||
|
));
|
||||||
|
|
||||||
// Setup the console.
|
// Setup the console.
|
||||||
let console = components::console::ConsoleComponent::new(board_kernel, uart_mux).finalize(());
|
let console = components::console::ConsoleComponent::new(
|
||||||
|
board_kernel,
|
||||||
|
capsules::console::DRIVER_NUM,
|
||||||
|
uart_mux,
|
||||||
|
)
|
||||||
|
.finalize(components::console_component_helper!());
|
||||||
// Create the debugger object that handles calls to `debug!()`.
|
// Create the debugger object that handles calls to `debug!()`.
|
||||||
components::debug_writer::DebugWriterComponent::new(uart_mux).finalize(());
|
components::debug_writer::DebugWriterComponent::new(uart_mux).finalize(());
|
||||||
|
|
||||||
let rng = components::rng::RngComponent::new(board_kernel, &base_peripherals.trng).finalize(());
|
let rng = components::rng::RngComponent::new(
|
||||||
|
board_kernel,
|
||||||
|
capsules::rng::DRIVER_NUM,
|
||||||
|
&base_peripherals.trng,
|
||||||
|
)
|
||||||
|
.finalize(());
|
||||||
|
|
||||||
// Initialize AC using AIN5 (P0.29) as VIN+ and VIN- as AIN0 (P0.02)
|
// Initialize AC using AIN5 (P0.29) as VIN+ and VIN- as AIN0 (P0.02)
|
||||||
// These are hardcoded pin assignments specified in the driver
|
// These are hardcoded pin assignments specified in the driver
|
||||||
@@ -317,6 +398,8 @@ pub unsafe fn reset_handler() {
|
|||||||
nrf52840::acomp::Channel,
|
nrf52840::acomp::Channel,
|
||||||
&nrf52840::acomp::CHANNEL_AC0
|
&nrf52840::acomp::CHANNEL_AC0
|
||||||
),
|
),
|
||||||
|
board_kernel,
|
||||||
|
capsules::analog_comparator::DRIVER_NUM,
|
||||||
)
|
)
|
||||||
.finalize(components::acomp_component_buf!(
|
.finalize(components::acomp_component_buf!(
|
||||||
nrf52840::acomp::Comparator
|
nrf52840::acomp::Comparator
|
||||||
@@ -326,8 +409,9 @@ pub unsafe fn reset_handler() {
|
|||||||
nrf52840::nvmc::SyscallDriver,
|
nrf52840::nvmc::SyscallDriver,
|
||||||
nrf52840::nvmc::SyscallDriver::new(
|
nrf52840::nvmc::SyscallDriver::new(
|
||||||
&base_peripherals.nvmc,
|
&base_peripherals.nvmc,
|
||||||
board_kernel.create_grant(&memory_allocation_capability),
|
board_kernel.create_grant(nrf52840::nvmc::DRIVER_NUM, &memory_allocation_capability),
|
||||||
dynamic_deferred_caller,
|
dynamic_deferred_caller,
|
||||||
|
&mut APP_FLASH_BUFFER,
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
nvmc.set_deferred_handle(
|
nvmc.set_deferred_handle(
|
||||||
@@ -339,24 +423,20 @@ pub unsafe fn reset_handler() {
|
|||||||
// Configure USB controller
|
// Configure USB controller
|
||||||
let usb = components::usb_ctap::UsbCtapComponent::new(
|
let usb = components::usb_ctap::UsbCtapComponent::new(
|
||||||
board_kernel,
|
board_kernel,
|
||||||
|
capsules::usb::usb_ctap::DRIVER_NUM,
|
||||||
&nrf52840_peripherals.usbd,
|
&nrf52840_peripherals.usbd,
|
||||||
capsules::usb::usbc_client::MAX_CTRL_PACKET_SIZE_NRF52840,
|
capsules::usb::usbc_client::MAX_CTRL_PACKET_SIZE_NRF52840,
|
||||||
VENDOR_ID,
|
VENDOR_ID,
|
||||||
PRODUCT_ID,
|
PRODUCT_ID,
|
||||||
STRINGS,
|
STRINGS,
|
||||||
)
|
)
|
||||||
.finalize(components::usb_ctap_component_buf!(nrf52840::usbd::Usbd));
|
.finalize(components::usb_ctap_component_helper!(nrf52840::usbd::Usbd));
|
||||||
|
|
||||||
let crp = components::firmware_protection::FirmwareProtectionComponent::new(
|
|
||||||
board_kernel,
|
|
||||||
nrf52840::uicr::Uicr::new(),
|
|
||||||
)
|
|
||||||
.finalize(components::firmware_protection_component_helper!(
|
|
||||||
nrf52840::uicr::Uicr
|
|
||||||
));
|
|
||||||
|
|
||||||
nrf52_components::NrfClockComponent::new(&base_peripherals.clock).finalize(());
|
nrf52_components::NrfClockComponent::new(&base_peripherals.clock).finalize(());
|
||||||
|
|
||||||
|
let scheduler = components::sched::round_robin::RoundRobinComponent::new(&PROCESSES)
|
||||||
|
.finalize(components::rr_component_helper!(NUM_PROCS));
|
||||||
|
|
||||||
let platform = Platform {
|
let platform = Platform {
|
||||||
button,
|
button,
|
||||||
pconsole,
|
pconsole,
|
||||||
@@ -368,15 +448,20 @@ pub unsafe fn reset_handler() {
|
|||||||
analog_comparator,
|
analog_comparator,
|
||||||
nvmc,
|
nvmc,
|
||||||
usb,
|
usb,
|
||||||
crp,
|
ipc: kernel::ipc::IPC::new(
|
||||||
ipc: kernel::ipc::IPC::new(board_kernel, &memory_allocation_capability),
|
board_kernel,
|
||||||
|
kernel::ipc::DRIVER_NUM,
|
||||||
|
&memory_allocation_capability,
|
||||||
|
),
|
||||||
|
scheduler,
|
||||||
|
systick: cortexm4::systick::SysTick::new_with_calibration(6400_0000),
|
||||||
};
|
};
|
||||||
|
|
||||||
platform.pconsole.start();
|
let _ = platform.pconsole.start();
|
||||||
debug!("Initialization complete. Entering main loop\r");
|
debug!("Initialization complete. Entering main loop\r");
|
||||||
debug!("{}", &nrf52840::ficr::FICR_INSTANCE);
|
debug!("{}", &nrf52840::ficr::FICR_INSTANCE);
|
||||||
|
|
||||||
/// These symbols are defined in the linker script.
|
// These symbols are defined in the linker script.
|
||||||
extern "C" {
|
extern "C" {
|
||||||
/// Beginning of the ROM region containing app images.
|
/// Beginning of the ROM region containing app images.
|
||||||
static _sapps: u8;
|
static _sapps: u8;
|
||||||
@@ -388,7 +473,7 @@ pub unsafe fn reset_handler() {
|
|||||||
static _eappmem: u8;
|
static _eappmem: u8;
|
||||||
}
|
}
|
||||||
|
|
||||||
kernel::procs::load_processes(
|
kernel::process::load_processes(
|
||||||
board_kernel,
|
board_kernel,
|
||||||
chip,
|
chip,
|
||||||
core::slice::from_raw_parts(
|
core::slice::from_raw_parts(
|
||||||
@@ -400,7 +485,7 @@ pub unsafe fn reset_handler() {
|
|||||||
&_eappmem as *const u8 as usize - &_sappmem as *const u8 as usize,
|
&_eappmem as *const u8 as usize - &_sappmem as *const u8 as usize,
|
||||||
),
|
),
|
||||||
&mut PROCESSES,
|
&mut PROCESSES,
|
||||||
FAULT_RESPONSE,
|
&FAULT_RESPONSE,
|
||||||
&process_management_capability,
|
&process_management_capability,
|
||||||
)
|
)
|
||||||
.unwrap_or_else(|err| {
|
.unwrap_or_else(|err| {
|
||||||
@@ -408,13 +493,5 @@ pub unsafe fn reset_handler() {
|
|||||||
debug!("{:?}", err);
|
debug!("{:?}", err);
|
||||||
});
|
});
|
||||||
|
|
||||||
let scheduler = components::sched::round_robin::RoundRobinComponent::new(&PROCESSES)
|
board_kernel.kernel_loop(&platform, chip, Some(&platform.ipc), &main_loop_capability);
|
||||||
.finalize(components::rr_component_helper!(NUM_PROCS));
|
|
||||||
board_kernel.kernel_loop(
|
|
||||||
&platform,
|
|
||||||
chip,
|
|
||||||
Some(&platform.ipc),
|
|
||||||
scheduler,
|
|
||||||
&main_loop_capability,
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,8 +7,7 @@ use kernel::hil::led;
|
|||||||
use kernel::hil::uart::{self, Configure};
|
use kernel::hil::uart::{self, Configure};
|
||||||
use nrf52840::gpio::Pin;
|
use nrf52840::gpio::Pin;
|
||||||
|
|
||||||
use crate::CHIP;
|
use crate::{CHIP, PROCESSES, PROCESS_PRINTER};
|
||||||
use crate::PROCESSES;
|
|
||||||
|
|
||||||
struct Writer {
|
struct Writer {
|
||||||
initialized: bool,
|
initialized: bool,
|
||||||
@@ -31,7 +30,7 @@ impl IoWrite for Writer {
|
|||||||
let uart = nrf52840::uart::Uarte::new();
|
let uart = nrf52840::uart::Uarte::new();
|
||||||
if !self.initialized {
|
if !self.initialized {
|
||||||
self.initialized = true;
|
self.initialized = true;
|
||||||
uart.configure(uart::Parameters {
|
let _ = uart.configure(uart::Parameters {
|
||||||
baud_rate: 115200,
|
baud_rate: 115200,
|
||||||
stop_bits: uart::StopBits::One,
|
stop_bits: uart::StopBits::One,
|
||||||
parity: uart::Parity::None,
|
parity: uart::Parity::None,
|
||||||
@@ -64,5 +63,6 @@ pub unsafe extern "C" fn panic_fmt(pi: &PanicInfo) -> ! {
|
|||||||
&cortexm4::support::nop,
|
&cortexm4::support::nop,
|
||||||
&PROCESSES,
|
&PROCESSES,
|
||||||
&CHIP,
|
&CHIP,
|
||||||
|
&PROCESS_PRINTER,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,13 +7,15 @@
|
|||||||
// Disable this attribute when documenting, as a workaround for
|
// Disable this attribute when documenting, as a workaround for
|
||||||
// https://github.com/rust-lang/rust/issues/62184.
|
// https://github.com/rust-lang/rust/issues/62184.
|
||||||
#![cfg_attr(not(doc), no_main)]
|
#![cfg_attr(not(doc), no_main)]
|
||||||
#![feature(const_in_array_repeat_expressions)]
|
|
||||||
#![deny(missing_docs)]
|
#![deny(missing_docs)]
|
||||||
|
|
||||||
use kernel::common::dynamic_deferred_call::{DynamicDeferredCall, DynamicDeferredCallClientState};
|
use capsules::virtual_alarm::VirtualMuxAlarm;
|
||||||
use kernel::component::Component;
|
use kernel::component::Component;
|
||||||
|
use kernel::dynamic_deferred_call::{DynamicDeferredCall, DynamicDeferredCallClientState};
|
||||||
use kernel::hil::led::LedLow;
|
use kernel::hil::led::LedLow;
|
||||||
use kernel::hil::time::Counter;
|
use kernel::hil::time::Counter;
|
||||||
|
use kernel::platform::{KernelResources, SyscallDriverLookup, SyscallFilter};
|
||||||
|
use kernel::scheduler::round_robin::RoundRobinSched;
|
||||||
#[allow(unused_imports)]
|
#[allow(unused_imports)]
|
||||||
use kernel::{capabilities, create_capability, debug, debug_gpio, debug_verbose, static_init};
|
use kernel::{capabilities, create_capability, debug, debug_gpio, debug_verbose, static_init};
|
||||||
use nrf52840::gpio::Pin;
|
use nrf52840::gpio::Pin;
|
||||||
@@ -46,16 +48,20 @@ static STRINGS: &'static [&'static str] = &[
|
|||||||
"OpenSK",
|
"OpenSK",
|
||||||
// Serial number
|
// Serial number
|
||||||
"v1.0",
|
"v1.0",
|
||||||
|
// Interface description + main HID string
|
||||||
|
"FIDO2",
|
||||||
|
// vendor HID string
|
||||||
|
"Vendor HID",
|
||||||
];
|
];
|
||||||
|
|
||||||
// State for loading and holding applications.
|
// State for loading and holding applications.
|
||||||
// How should the kernel respond when a process faults.
|
// How should the kernel respond when a process faults.
|
||||||
const FAULT_RESPONSE: kernel::procs::FaultResponse = kernel::procs::FaultResponse::Panic;
|
const FAULT_RESPONSE: kernel::process::PanicFaultPolicy = kernel::process::PanicFaultPolicy {};
|
||||||
|
|
||||||
// Number of concurrent processes this platform supports.
|
// Number of concurrent processes this platform supports.
|
||||||
const NUM_PROCS: usize = 8;
|
const NUM_PROCS: usize = 8;
|
||||||
|
|
||||||
static mut PROCESSES: [Option<&'static dyn kernel::procs::ProcessType>; NUM_PROCS] =
|
static mut PROCESSES: [Option<&'static dyn kernel::process::Process>; NUM_PROCS] =
|
||||||
[None; NUM_PROCS];
|
[None; NUM_PROCS];
|
||||||
|
|
||||||
static mut STORAGE_LOCATIONS: [kernel::StorageLocation; 2] = [
|
static mut STORAGE_LOCATIONS: [kernel::StorageLocation; 2] = [
|
||||||
@@ -74,6 +80,9 @@ static mut STORAGE_LOCATIONS: [kernel::StorageLocation; 2] = [
|
|||||||
|
|
||||||
// Static reference to chip for panic dumps
|
// Static reference to chip for panic dumps
|
||||||
static mut CHIP: Option<&'static nrf52840::chip::NRF52<Nrf52840DefaultPeripherals>> = None;
|
static mut CHIP: Option<&'static nrf52840::chip::NRF52<Nrf52840DefaultPeripherals>> = None;
|
||||||
|
static mut PROCESS_PRINTER: Option<&'static kernel::process::ProcessPrinterText> = None;
|
||||||
|
/// Flash buffer for the custom nvmc driver
|
||||||
|
static mut APP_FLASH_BUFFER: [u8; 0x1000] = [0; 0x1000];
|
||||||
|
|
||||||
/// Dummy buffer that causes the linker to reserve enough space for the stack.
|
/// Dummy buffer that causes the linker to reserve enough space for the stack.
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
@@ -85,16 +94,18 @@ pub struct Platform {
|
|||||||
button: &'static capsules::button::Button<'static, nrf52840::gpio::GPIOPin<'static>>,
|
button: &'static capsules::button::Button<'static, nrf52840::gpio::GPIOPin<'static>>,
|
||||||
pconsole: &'static capsules::process_console::ProcessConsole<
|
pconsole: &'static capsules::process_console::ProcessConsole<
|
||||||
'static,
|
'static,
|
||||||
|
VirtualMuxAlarm<'static, nrf52840::rtc::Rtc<'static>>,
|
||||||
components::process_console::Capability,
|
components::process_console::Capability,
|
||||||
>,
|
>,
|
||||||
console: &'static capsules::console::Console<'static>,
|
console: &'static capsules::console::Console<'static>,
|
||||||
gpio: &'static capsules::gpio::GPIO<'static, nrf52840::gpio::GPIOPin<'static>>,
|
gpio: &'static capsules::gpio::GPIO<'static, nrf52840::gpio::GPIOPin<'static>>,
|
||||||
led: &'static capsules::led::LedDriver<
|
led: &'static capsules::led::LedDriver<
|
||||||
'static,
|
'static,
|
||||||
LedLow<'static, nrf52840::gpio::GPIOPin<'static>>,
|
kernel::hil::led::LedLow<'static, nrf52840::gpio::GPIOPin<'static>>,
|
||||||
|
3,
|
||||||
>,
|
>,
|
||||||
rng: &'static capsules::rng::RngDriver<'static>,
|
rng: &'static capsules::rng::RngDriver<'static>,
|
||||||
ipc: kernel::ipc::IPC<NUM_PROCS>,
|
ipc: kernel::ipc::IPC<{ NUM_PROCS as u8 }>,
|
||||||
analog_comparator: &'static capsules::analog_comparator::AnalogComparator<
|
analog_comparator: &'static capsules::analog_comparator::AnalogComparator<
|
||||||
'static,
|
'static,
|
||||||
nrf52840::acomp::Comparator<'static>,
|
nrf52840::acomp::Comparator<'static>,
|
||||||
@@ -103,6 +114,8 @@ pub struct Platform {
|
|||||||
'static,
|
'static,
|
||||||
capsules::virtual_alarm::VirtualMuxAlarm<'static, nrf52840::rtc::Rtc<'static>>,
|
capsules::virtual_alarm::VirtualMuxAlarm<'static, nrf52840::rtc::Rtc<'static>>,
|
||||||
>,
|
>,
|
||||||
|
scheduler: &'static RoundRobinSched<'static>,
|
||||||
|
systick: cortexm4::systick::SysTick,
|
||||||
nvmc: &'static nrf52840::nvmc::SyscallDriver,
|
nvmc: &'static nrf52840::nvmc::SyscallDriver,
|
||||||
usb: &'static capsules::usb::usb_ctap::CtapUsbSyscallDriver<
|
usb: &'static capsules::usb::usb_ctap::CtapUsbSyscallDriver<
|
||||||
'static,
|
'static,
|
||||||
@@ -111,10 +124,10 @@ pub struct Platform {
|
|||||||
>,
|
>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl kernel::Platform for Platform {
|
impl SyscallDriverLookup for Platform {
|
||||||
fn with_driver<F, R>(&self, driver_num: usize, f: F) -> R
|
fn with_driver<F, R>(&self, driver_num: usize, f: F) -> R
|
||||||
where
|
where
|
||||||
F: FnOnce(Option<&dyn kernel::Driver>) -> R,
|
F: FnOnce(Option<&dyn kernel::syscall::SyscallDriver>) -> R,
|
||||||
{
|
{
|
||||||
match driver_num {
|
match driver_num {
|
||||||
capsules::console::DRIVER_NUM => f(Some(self.console)),
|
capsules::console::DRIVER_NUM => f(Some(self.console)),
|
||||||
@@ -130,39 +143,82 @@ impl kernel::Platform for Platform {
|
|||||||
_ => f(None),
|
_ => f(None),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl SyscallFilter for Platform {
|
||||||
fn filter_syscall(
|
fn filter_syscall(
|
||||||
&self,
|
&self,
|
||||||
process: &dyn kernel::procs::ProcessType,
|
process: &dyn kernel::process::Process,
|
||||||
syscall: &kernel::syscall::Syscall,
|
syscall: &kernel::syscall::Syscall,
|
||||||
) -> Result<(), kernel::ReturnCode> {
|
) -> Result<(), kernel::errorcode::ErrorCode> {
|
||||||
use kernel::syscall::Syscall;
|
use kernel::syscall::Syscall;
|
||||||
match *syscall {
|
match *syscall {
|
||||||
Syscall::COMMAND {
|
Syscall::Command {
|
||||||
driver_number: nrf52840::nvmc::DRIVER_NUM,
|
driver_number: nrf52840::nvmc::DRIVER_NUM,
|
||||||
subdriver_number: cmd,
|
subdriver_number: cmd,
|
||||||
arg0: ptr,
|
arg0: ptr,
|
||||||
arg1: len,
|
arg1: len,
|
||||||
} if (cmd == 2 || cmd == 3) && !process.fits_in_storage_location(ptr, len) => {
|
} if (cmd == 2 || cmd == 3) && !process.fits_in_storage_location(ptr, len) => {
|
||||||
Err(kernel::ReturnCode::EINVAL)
|
Err(kernel::ErrorCode::INVAL)
|
||||||
}
|
}
|
||||||
_ => Ok(()),
|
_ => Ok(()),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Entry point in the vector table called on hard reset.
|
/// This is in a separate, inline(never) function so that its stack frame is
|
||||||
#[no_mangle]
|
/// removed when this function returns. Otherwise, the stack space used for
|
||||||
pub unsafe fn reset_handler() {
|
/// these static_inits is wasted.
|
||||||
// Loads relocations and clears BSS
|
#[inline(never)]
|
||||||
nrf52840::init();
|
unsafe fn get_peripherals() -> &'static mut Nrf52840DefaultPeripherals<'static> {
|
||||||
|
|
||||||
let ppi = static_init!(nrf52840::ppi::Ppi, nrf52840::ppi::Ppi::new());
|
|
||||||
// Initialize chip peripheral drivers
|
// Initialize chip peripheral drivers
|
||||||
let nrf52840_peripherals = static_init!(
|
let nrf52840_peripherals = static_init!(
|
||||||
Nrf52840DefaultPeripherals,
|
Nrf52840DefaultPeripherals,
|
||||||
Nrf52840DefaultPeripherals::new(ppi)
|
Nrf52840DefaultPeripherals::new()
|
||||||
);
|
);
|
||||||
|
nrf52840_peripherals
|
||||||
|
}
|
||||||
|
impl KernelResources<nrf52840::chip::NRF52<'static, Nrf52840DefaultPeripherals<'static>>>
|
||||||
|
for Platform
|
||||||
|
{
|
||||||
|
type SyscallDriverLookup = Self;
|
||||||
|
type SyscallFilter = Self;
|
||||||
|
type ProcessFault = ();
|
||||||
|
type Scheduler = RoundRobinSched<'static>;
|
||||||
|
type SchedulerTimer = cortexm4::systick::SysTick;
|
||||||
|
type WatchDog = ();
|
||||||
|
type ContextSwitchCallback = ();
|
||||||
|
fn syscall_driver_lookup(&self) -> &Self::SyscallDriverLookup {
|
||||||
|
&self
|
||||||
|
}
|
||||||
|
fn syscall_filter(&self) -> &Self::SyscallFilter {
|
||||||
|
&self
|
||||||
|
}
|
||||||
|
fn process_fault(&self) -> &Self::ProcessFault {
|
||||||
|
&()
|
||||||
|
}
|
||||||
|
fn scheduler(&self) -> &Self::Scheduler {
|
||||||
|
self.scheduler
|
||||||
|
}
|
||||||
|
fn scheduler_timer(&self) -> &Self::SchedulerTimer {
|
||||||
|
&self.systick
|
||||||
|
}
|
||||||
|
fn watchdog(&self) -> &Self::WatchDog {
|
||||||
|
&()
|
||||||
|
}
|
||||||
|
fn context_switch_callback(&self) -> &Self::ContextSwitchCallback {
|
||||||
|
&()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Main function called after RAM initialized.
|
||||||
|
#[no_mangle]
|
||||||
|
pub unsafe fn main() {
|
||||||
|
// Loads relocations and clears BSS
|
||||||
|
nrf52840::init();
|
||||||
|
|
||||||
|
// Initialize chip peripheral drivers
|
||||||
|
let nrf52840_peripherals = get_peripherals();
|
||||||
|
|
||||||
// set up circular peripheral dependencies
|
// set up circular peripheral dependencies
|
||||||
nrf52840_peripherals.init();
|
nrf52840_peripherals.init();
|
||||||
@@ -175,6 +231,7 @@ pub unsafe fn reset_handler() {
|
|||||||
// GPIOs
|
// GPIOs
|
||||||
let gpio = components::gpio::GpioComponent::new(
|
let gpio = components::gpio::GpioComponent::new(
|
||||||
board_kernel,
|
board_kernel,
|
||||||
|
capsules::gpio::DRIVER_NUM,
|
||||||
components::gpio_component_helper!(
|
components::gpio_component_helper!(
|
||||||
nrf52840::gpio::GPIOPin,
|
nrf52840::gpio::GPIOPin,
|
||||||
// left side of the USB plug. Right side is used for UART
|
// left side of the USB plug. Right side is used for UART
|
||||||
@@ -189,6 +246,7 @@ pub unsafe fn reset_handler() {
|
|||||||
|
|
||||||
let button = components::button::ButtonComponent::new(
|
let button = components::button::ButtonComponent::new(
|
||||||
board_kernel,
|
board_kernel,
|
||||||
|
capsules::button::DRIVER_NUM,
|
||||||
components::button_component_helper!(
|
components::button_component_helper!(
|
||||||
nrf52840::gpio::GPIOPin,
|
nrf52840::gpio::GPIOPin,
|
||||||
(
|
(
|
||||||
@@ -200,14 +258,11 @@ pub unsafe fn reset_handler() {
|
|||||||
)
|
)
|
||||||
.finalize(components::button_component_buf!(nrf52840::gpio::GPIOPin));
|
.finalize(components::button_component_buf!(nrf52840::gpio::GPIOPin));
|
||||||
|
|
||||||
let led = components::led::LedsComponent::new(components::led_component_helper!(
|
let led = components::led::LedsComponent::new().finalize(components::led_component_helper!(
|
||||||
LedLow<'static, nrf52840::gpio::GPIOPin>,
|
LedLow<'static, nrf52840::gpio::GPIOPin>,
|
||||||
LedLow::new(&nrf52840_peripherals.gpio_port[LED1_R_PIN]),
|
LedLow::new(&nrf52840_peripherals.gpio_port[LED1_R_PIN]),
|
||||||
LedLow::new(&nrf52840_peripherals.gpio_port[LED1_G_PIN]),
|
LedLow::new(&nrf52840_peripherals.gpio_port[LED1_G_PIN]),
|
||||||
LedLow::new(&nrf52840_peripherals.gpio_port[LED1_B_PIN]),
|
LedLow::new(&nrf52840_peripherals.gpio_port[LED1_B_PIN]),
|
||||||
))
|
|
||||||
.finalize(components::led_component_buf!(
|
|
||||||
LedLow<'static, nrf52840::gpio::GPIOPin>
|
|
||||||
));
|
));
|
||||||
|
|
||||||
let chip = static_init!(
|
let chip = static_init!(
|
||||||
@@ -233,10 +288,14 @@ pub unsafe fn reset_handler() {
|
|||||||
);
|
);
|
||||||
|
|
||||||
let rtc = &base_peripherals.rtc;
|
let rtc = &base_peripherals.rtc;
|
||||||
rtc.start();
|
let _ = rtc.start();
|
||||||
let mux_alarm = components::alarm::AlarmMuxComponent::new(rtc)
|
let mux_alarm = components::alarm::AlarmMuxComponent::new(rtc)
|
||||||
.finalize(components::alarm_mux_component_helper!(nrf52840::rtc::Rtc));
|
.finalize(components::alarm_mux_component_helper!(nrf52840::rtc::Rtc));
|
||||||
let alarm = components::alarm::AlarmDriverComponent::new(board_kernel, mux_alarm)
|
let alarm = components::alarm::AlarmDriverComponent::new(
|
||||||
|
board_kernel,
|
||||||
|
capsules::alarm::DRIVER_NUM,
|
||||||
|
mux_alarm,
|
||||||
|
)
|
||||||
.finalize(components::alarm_component_helper!(nrf52840::rtc::Rtc));
|
.finalize(components::alarm_component_helper!(nrf52840::rtc::Rtc));
|
||||||
let uart_channel = UartChannel::Pins(UartPins::new(UART_RTS, UART_TXD, UART_CTS, UART_RXD));
|
let uart_channel = UartChannel::Pins(UartPins::new(UART_RTS, UART_TXD, UART_CTS, UART_RXD));
|
||||||
let channel = nrf52_components::UartChannelComponent::new(
|
let channel = nrf52_components::UartChannelComponent::new(
|
||||||
@@ -253,22 +312,40 @@ pub unsafe fn reset_handler() {
|
|||||||
DynamicDeferredCall::new(dynamic_deferred_call_clients)
|
DynamicDeferredCall::new(dynamic_deferred_call_clients)
|
||||||
);
|
);
|
||||||
DynamicDeferredCall::set_global_instance(dynamic_deferred_caller);
|
DynamicDeferredCall::set_global_instance(dynamic_deferred_caller);
|
||||||
|
let process_printer =
|
||||||
|
components::process_printer::ProcessPrinterTextComponent::new().finalize(());
|
||||||
|
PROCESS_PRINTER = Some(process_printer);
|
||||||
|
|
||||||
// Create a shared UART channel for the console and for kernel debug.
|
// Create a shared UART channel for the console and for kernel debug.
|
||||||
let uart_mux =
|
let uart_mux =
|
||||||
components::console::UartMuxComponent::new(channel, 115200, dynamic_deferred_caller)
|
components::console::UartMuxComponent::new(channel, 115200, dynamic_deferred_caller)
|
||||||
.finalize(());
|
.finalize(());
|
||||||
|
|
||||||
let pconsole =
|
let pconsole = components::process_console::ProcessConsoleComponent::new(
|
||||||
components::process_console::ProcessConsoleComponent::new(board_kernel, uart_mux)
|
board_kernel,
|
||||||
.finalize(());
|
uart_mux,
|
||||||
|
mux_alarm,
|
||||||
|
process_printer,
|
||||||
|
)
|
||||||
|
.finalize(components::process_console_component_helper!(
|
||||||
|
nrf52840::rtc::Rtc<'static>
|
||||||
|
));
|
||||||
|
|
||||||
// Setup the console.
|
// Setup the console.
|
||||||
let console = components::console::ConsoleComponent::new(board_kernel, uart_mux).finalize(());
|
let console = components::console::ConsoleComponent::new(
|
||||||
|
board_kernel,
|
||||||
|
capsules::console::DRIVER_NUM,
|
||||||
|
uart_mux,
|
||||||
|
)
|
||||||
|
.finalize(components::console_component_helper!());
|
||||||
// Create the debugger object that handles calls to `debug!()`.
|
// Create the debugger object that handles calls to `debug!()`.
|
||||||
components::debug_writer::DebugWriterComponent::new(uart_mux).finalize(());
|
components::debug_writer::DebugWriterComponent::new(uart_mux).finalize(());
|
||||||
|
let rng = components::rng::RngComponent::new(
|
||||||
let rng = components::rng::RngComponent::new(board_kernel, &base_peripherals.trng).finalize(());
|
board_kernel,
|
||||||
|
capsules::rng::DRIVER_NUM,
|
||||||
|
&base_peripherals.trng,
|
||||||
|
)
|
||||||
|
.finalize(());
|
||||||
|
|
||||||
// Initialize AC using AIN5 (P0.29) as VIN+ and VIN- as AIN0 (P0.02)
|
// Initialize AC using AIN5 (P0.29) as VIN+ and VIN- as AIN0 (P0.02)
|
||||||
// These are hardcoded pin assignments specified in the driver
|
// These are hardcoded pin assignments specified in the driver
|
||||||
@@ -278,6 +355,8 @@ pub unsafe fn reset_handler() {
|
|||||||
nrf52840::acomp::Channel,
|
nrf52840::acomp::Channel,
|
||||||
&nrf52840::acomp::CHANNEL_AC0
|
&nrf52840::acomp::CHANNEL_AC0
|
||||||
),
|
),
|
||||||
|
board_kernel,
|
||||||
|
capsules::analog_comparator::DRIVER_NUM,
|
||||||
)
|
)
|
||||||
.finalize(components::acomp_component_buf!(
|
.finalize(components::acomp_component_buf!(
|
||||||
nrf52840::acomp::Comparator
|
nrf52840::acomp::Comparator
|
||||||
@@ -287,8 +366,9 @@ pub unsafe fn reset_handler() {
|
|||||||
nrf52840::nvmc::SyscallDriver,
|
nrf52840::nvmc::SyscallDriver,
|
||||||
nrf52840::nvmc::SyscallDriver::new(
|
nrf52840::nvmc::SyscallDriver::new(
|
||||||
&base_peripherals.nvmc,
|
&base_peripherals.nvmc,
|
||||||
board_kernel.create_grant(&memory_allocation_capability),
|
board_kernel.create_grant(nrf52840::nvmc::DRIVER_NUM, &memory_allocation_capability),
|
||||||
dynamic_deferred_caller,
|
dynamic_deferred_caller,
|
||||||
|
&mut APP_FLASH_BUFFER,
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
nvmc.set_deferred_handle(
|
nvmc.set_deferred_handle(
|
||||||
@@ -300,16 +380,20 @@ pub unsafe fn reset_handler() {
|
|||||||
// Configure USB controller
|
// Configure USB controller
|
||||||
let usb = components::usb_ctap::UsbCtapComponent::new(
|
let usb = components::usb_ctap::UsbCtapComponent::new(
|
||||||
board_kernel,
|
board_kernel,
|
||||||
|
capsules::usb::usb_ctap::DRIVER_NUM,
|
||||||
&nrf52840_peripherals.usbd,
|
&nrf52840_peripherals.usbd,
|
||||||
capsules::usb::usbc_client::MAX_CTRL_PACKET_SIZE_NRF52840,
|
capsules::usb::usbc_client::MAX_CTRL_PACKET_SIZE_NRF52840,
|
||||||
VENDOR_ID,
|
VENDOR_ID,
|
||||||
PRODUCT_ID,
|
PRODUCT_ID,
|
||||||
STRINGS,
|
STRINGS,
|
||||||
)
|
)
|
||||||
.finalize(components::usb_ctap_component_buf!(nrf52840::usbd::Usbd));
|
.finalize(components::usb_ctap_component_helper!(nrf52840::usbd::Usbd));
|
||||||
|
|
||||||
nrf52_components::NrfClockComponent::new(&base_peripherals.clock).finalize(());
|
nrf52_components::NrfClockComponent::new(&base_peripherals.clock).finalize(());
|
||||||
|
|
||||||
|
let scheduler = components::sched::round_robin::RoundRobinComponent::new(&PROCESSES)
|
||||||
|
.finalize(components::rr_component_helper!(NUM_PROCS));
|
||||||
|
|
||||||
let platform = Platform {
|
let platform = Platform {
|
||||||
button,
|
button,
|
||||||
pconsole,
|
pconsole,
|
||||||
@@ -321,14 +405,20 @@ pub unsafe fn reset_handler() {
|
|||||||
analog_comparator,
|
analog_comparator,
|
||||||
nvmc,
|
nvmc,
|
||||||
usb,
|
usb,
|
||||||
ipc: kernel::ipc::IPC::new(board_kernel, &memory_allocation_capability),
|
ipc: kernel::ipc::IPC::new(
|
||||||
|
board_kernel,
|
||||||
|
kernel::ipc::DRIVER_NUM,
|
||||||
|
&memory_allocation_capability,
|
||||||
|
),
|
||||||
|
scheduler,
|
||||||
|
systick: cortexm4::systick::SysTick::new_with_calibration(64000000),
|
||||||
};
|
};
|
||||||
|
|
||||||
platform.pconsole.start();
|
let _ = platform.pconsole.start();
|
||||||
debug!("Initialization complete. Entering main loop\r");
|
debug!("Initialization complete. Entering main loop\r");
|
||||||
debug!("{}", &nrf52840::ficr::FICR_INSTANCE);
|
debug!("{}", &nrf52840::ficr::FICR_INSTANCE);
|
||||||
|
|
||||||
/// These symbols are defined in the linker script.
|
// These symbols are defined in the linker script.
|
||||||
extern "C" {
|
extern "C" {
|
||||||
/// Beginning of the ROM region containing app images.
|
/// Beginning of the ROM region containing app images.
|
||||||
static _sapps: u8;
|
static _sapps: u8;
|
||||||
@@ -340,7 +430,7 @@ pub unsafe fn reset_handler() {
|
|||||||
static _eappmem: u8;
|
static _eappmem: u8;
|
||||||
}
|
}
|
||||||
|
|
||||||
kernel::procs::load_processes(
|
kernel::process::load_processes(
|
||||||
board_kernel,
|
board_kernel,
|
||||||
chip,
|
chip,
|
||||||
core::slice::from_raw_parts(
|
core::slice::from_raw_parts(
|
||||||
@@ -352,7 +442,7 @@ pub unsafe fn reset_handler() {
|
|||||||
&_eappmem as *const u8 as usize - &_sappmem as *const u8 as usize,
|
&_eappmem as *const u8 as usize - &_sappmem as *const u8 as usize,
|
||||||
),
|
),
|
||||||
&mut PROCESSES,
|
&mut PROCESSES,
|
||||||
FAULT_RESPONSE,
|
&FAULT_RESPONSE,
|
||||||
&process_management_capability,
|
&process_management_capability,
|
||||||
)
|
)
|
||||||
.unwrap_or_else(|err| {
|
.unwrap_or_else(|err| {
|
||||||
@@ -360,13 +450,5 @@ pub unsafe fn reset_handler() {
|
|||||||
debug!("{:?}", err);
|
debug!("{:?}", err);
|
||||||
});
|
});
|
||||||
|
|
||||||
let scheduler = components::sched::round_robin::RoundRobinComponent::new(&PROCESSES)
|
board_kernel.kernel_loop(&platform, chip, Some(&platform.ipc), &main_loop_capability);
|
||||||
.finalize(components::rr_component_helper!(NUM_PROCS));
|
|
||||||
board_kernel.kernel_loop(
|
|
||||||
&platform,
|
|
||||||
chip,
|
|
||||||
Some(&platform.ipc),
|
|
||||||
scheduler,
|
|
||||||
&main_loop_capability,
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,6 +10,7 @@ use nrf52840::gpio::Pin;
|
|||||||
|
|
||||||
use crate::CHIP;
|
use crate::CHIP;
|
||||||
use crate::PROCESSES;
|
use crate::PROCESSES;
|
||||||
|
use crate::PROCESS_PRINTER;
|
||||||
|
|
||||||
enum Writer {
|
enum Writer {
|
||||||
WriterUart(/* initialized */ bool),
|
WriterUart(/* initialized */ bool),
|
||||||
@@ -48,7 +49,7 @@ impl IoWrite for Writer {
|
|||||||
let uart = nrf52840::uart::Uarte::new();
|
let uart = nrf52840::uart::Uarte::new();
|
||||||
if !*initialized {
|
if !*initialized {
|
||||||
*initialized = true;
|
*initialized = true;
|
||||||
uart.configure(uart::Parameters {
|
let _ = uart.configure(uart::Parameters {
|
||||||
baud_rate: 115200,
|
baud_rate: 115200,
|
||||||
stop_bits: uart::StopBits::One,
|
stop_bits: uart::StopBits::One,
|
||||||
parity: uart::Parity::None,
|
parity: uart::Parity::None,
|
||||||
@@ -102,5 +103,6 @@ pub unsafe extern "C" fn panic_fmt(pi: &PanicInfo) -> ! {
|
|||||||
&cortexm4::support::nop,
|
&cortexm4::support::nop,
|
||||||
&PROCESSES,
|
&PROCESSES,
|
||||||
&CHIP,
|
&CHIP,
|
||||||
|
&PROCESS_PRINTER,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -64,14 +64,16 @@
|
|||||||
// Disable this attribute when documenting, as a workaround for
|
// Disable this attribute when documenting, as a workaround for
|
||||||
// https://github.com/rust-lang/rust/issues/62184.
|
// https://github.com/rust-lang/rust/issues/62184.
|
||||||
#![cfg_attr(not(doc), no_main)]
|
#![cfg_attr(not(doc), no_main)]
|
||||||
#![feature(const_in_array_repeat_expressions)]
|
|
||||||
#![deny(missing_docs)]
|
#![deny(missing_docs)]
|
||||||
|
|
||||||
|
use capsules::virtual_alarm::VirtualMuxAlarm;
|
||||||
use core::env;
|
use core::env;
|
||||||
use kernel::common::dynamic_deferred_call::{DynamicDeferredCall, DynamicDeferredCallClientState};
|
|
||||||
use kernel::component::Component;
|
use kernel::component::Component;
|
||||||
|
use kernel::dynamic_deferred_call::{DynamicDeferredCall, DynamicDeferredCallClientState};
|
||||||
use kernel::hil::led::LedLow;
|
use kernel::hil::led::LedLow;
|
||||||
use kernel::hil::time::Counter;
|
use kernel::hil::time::Counter;
|
||||||
|
use kernel::platform::{KernelResources, SyscallDriverLookup, SyscallFilter};
|
||||||
|
use kernel::scheduler::round_robin::RoundRobinSched;
|
||||||
#[allow(unused_imports)]
|
#[allow(unused_imports)]
|
||||||
use kernel::{capabilities, create_capability, debug, debug_gpio, debug_verbose, static_init};
|
use kernel::{capabilities, create_capability, debug, debug_gpio, debug_verbose, static_init};
|
||||||
use nrf52840::gpio::Pin;
|
use nrf52840::gpio::Pin;
|
||||||
@@ -117,32 +119,41 @@ static STRINGS: &'static [&'static str] = &[
|
|||||||
"OpenSK",
|
"OpenSK",
|
||||||
// Serial number
|
// Serial number
|
||||||
"v1.0",
|
"v1.0",
|
||||||
|
// Interface description + main HID string
|
||||||
|
"FIDO2",
|
||||||
|
// vendor HID string
|
||||||
|
"Vendor HID",
|
||||||
];
|
];
|
||||||
|
|
||||||
// State for loading and holding applications.
|
// State for loading and holding applications.
|
||||||
// How should the kernel respond when a process faults.
|
// How should the kernel respond when a process faults.
|
||||||
const FAULT_RESPONSE: kernel::procs::FaultResponse = kernel::procs::FaultResponse::Panic;
|
const FAULT_RESPONSE: kernel::process::PanicFaultPolicy = kernel::process::PanicFaultPolicy {};
|
||||||
|
|
||||||
// Number of concurrent processes this platform supports.
|
// Number of concurrent processes this platform supports.
|
||||||
const NUM_PROCS: usize = 8;
|
const NUM_PROCS: usize = 8;
|
||||||
|
|
||||||
static mut PROCESSES: [Option<&'static dyn kernel::procs::ProcessType>; NUM_PROCS] =
|
static mut PROCESSES: [Option<&'static dyn kernel::process::Process>; NUM_PROCS] =
|
||||||
[None; NUM_PROCS];
|
[None; NUM_PROCS];
|
||||||
|
|
||||||
include!(concat!(env!("OUT_DIR"), "/locations.rs"));
|
include!(concat!(env!("OUT_DIR"), "/locations.rs"));
|
||||||
|
|
||||||
static mut CHIP: Option<&'static nrf52840::chip::NRF52<Nrf52840DefaultPeripherals>> = None;
|
static mut CHIP: Option<&'static nrf52840::chip::NRF52<Nrf52840DefaultPeripherals>> = None;
|
||||||
|
static mut PROCESS_PRINTER: Option<&'static kernel::process::ProcessPrinterText> = None;
|
||||||
|
|
||||||
|
/// Flash buffer for the custom nvmc driver
|
||||||
|
static mut APP_FLASH_BUFFER: [u8; 0x1000] = [0; 0x1000];
|
||||||
|
|
||||||
/// Dummy buffer that causes the linker to reserve enough space for the stack.
|
/// Dummy buffer that causes the linker to reserve enough space for the stack.
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
#[link_section = ".stack_buffer"]
|
#[link_section = ".stack_buffer"]
|
||||||
pub static mut STACK_MEMORY: [u8; 0x1000] = [0; 0x1000];
|
pub static mut STACK_MEMORY: [u8; 0x2000] = [0; 0x2000];
|
||||||
|
|
||||||
/// Supported drivers by the platform
|
/// Supported drivers by the platform
|
||||||
pub struct Platform {
|
pub struct Platform {
|
||||||
button: &'static capsules::button::Button<'static, nrf52840::gpio::GPIOPin<'static>>,
|
button: &'static capsules::button::Button<'static, nrf52840::gpio::GPIOPin<'static>>,
|
||||||
pconsole: &'static capsules::process_console::ProcessConsole<
|
pconsole: &'static capsules::process_console::ProcessConsole<
|
||||||
'static,
|
'static,
|
||||||
|
VirtualMuxAlarm<'static, nrf52840::rtc::Rtc<'static>>,
|
||||||
components::process_console::Capability,
|
components::process_console::Capability,
|
||||||
>,
|
>,
|
||||||
console: &'static capsules::console::Console<'static>,
|
console: &'static capsules::console::Console<'static>,
|
||||||
@@ -150,9 +161,10 @@ pub struct Platform {
|
|||||||
led: &'static capsules::led::LedDriver<
|
led: &'static capsules::led::LedDriver<
|
||||||
'static,
|
'static,
|
||||||
kernel::hil::led::LedLow<'static, nrf52840::gpio::GPIOPin<'static>>,
|
kernel::hil::led::LedLow<'static, nrf52840::gpio::GPIOPin<'static>>,
|
||||||
|
4,
|
||||||
>,
|
>,
|
||||||
rng: &'static capsules::rng::RngDriver<'static>,
|
rng: &'static capsules::rng::RngDriver<'static>,
|
||||||
ipc: kernel::ipc::IPC<NUM_PROCS>,
|
ipc: kernel::ipc::IPC<{ NUM_PROCS as u8 }>,
|
||||||
analog_comparator: &'static capsules::analog_comparator::AnalogComparator<
|
analog_comparator: &'static capsules::analog_comparator::AnalogComparator<
|
||||||
'static,
|
'static,
|
||||||
nrf52840::acomp::Comparator<'static>,
|
nrf52840::acomp::Comparator<'static>,
|
||||||
@@ -167,13 +179,14 @@ pub struct Platform {
|
|||||||
'static,
|
'static,
|
||||||
nrf52840::usbd::Usbd<'static>,
|
nrf52840::usbd::Usbd<'static>,
|
||||||
>,
|
>,
|
||||||
crp: &'static capsules::firmware_protection::FirmwareProtection<nrf52840::uicr::Uicr>,
|
scheduler: &'static RoundRobinSched<'static>,
|
||||||
|
systick: cortexm4::systick::SysTick,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl kernel::Platform for Platform {
|
impl SyscallDriverLookup for Platform {
|
||||||
fn with_driver<F, R>(&self, driver_num: usize, f: F) -> R
|
fn with_driver<F, R>(&self, driver_num: usize, f: F) -> R
|
||||||
where
|
where
|
||||||
F: FnOnce(Option<&dyn kernel::Driver>) -> R,
|
F: FnOnce(Option<&dyn kernel::syscall::SyscallDriver>) -> R,
|
||||||
{
|
{
|
||||||
match driver_num {
|
match driver_num {
|
||||||
capsules::console::DRIVER_NUM => f(Some(self.console)),
|
capsules::console::DRIVER_NUM => f(Some(self.console)),
|
||||||
@@ -185,44 +198,89 @@ impl kernel::Platform for Platform {
|
|||||||
capsules::analog_comparator::DRIVER_NUM => f(Some(self.analog_comparator)),
|
capsules::analog_comparator::DRIVER_NUM => f(Some(self.analog_comparator)),
|
||||||
nrf52840::nvmc::DRIVER_NUM => f(Some(self.nvmc)),
|
nrf52840::nvmc::DRIVER_NUM => f(Some(self.nvmc)),
|
||||||
capsules::usb::usb_ctap::DRIVER_NUM => f(Some(self.usb)),
|
capsules::usb::usb_ctap::DRIVER_NUM => f(Some(self.usb)),
|
||||||
capsules::firmware_protection::DRIVER_NUM => f(Some(self.crp)),
|
|
||||||
kernel::ipc::DRIVER_NUM => f(Some(&self.ipc)),
|
kernel::ipc::DRIVER_NUM => f(Some(&self.ipc)),
|
||||||
_ => f(None),
|
_ => f(None),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl SyscallFilter for Platform {
|
||||||
fn filter_syscall(
|
fn filter_syscall(
|
||||||
&self,
|
&self,
|
||||||
process: &dyn kernel::procs::ProcessType,
|
process: &dyn kernel::process::Process,
|
||||||
syscall: &kernel::syscall::Syscall,
|
syscall: &kernel::syscall::Syscall,
|
||||||
) -> Result<(), kernel::ReturnCode> {
|
) -> Result<(), kernel::errorcode::ErrorCode> {
|
||||||
use kernel::syscall::Syscall;
|
use kernel::syscall::Syscall;
|
||||||
match *syscall {
|
match *syscall {
|
||||||
Syscall::COMMAND {
|
Syscall::Command {
|
||||||
driver_number: nrf52840::nvmc::DRIVER_NUM,
|
driver_number: nrf52840::nvmc::DRIVER_NUM,
|
||||||
subdriver_number: cmd,
|
subdriver_number: cmd,
|
||||||
arg0: ptr,
|
arg0: ptr,
|
||||||
arg1: len,
|
arg1: len,
|
||||||
} if (cmd == 2 || cmd == 3) && !process.fits_in_storage_location(ptr, len) => {
|
} if (cmd == 2 || cmd == 3) && !process.fits_in_storage_location(ptr, len) => {
|
||||||
Err(kernel::ReturnCode::EINVAL)
|
Err(kernel::ErrorCode::INVAL)
|
||||||
}
|
}
|
||||||
_ => Ok(()),
|
_ => Ok(()),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Entry point in the vector table called on hard reset.
|
/// This is in a separate, inline(never) function so that its stack frame is
|
||||||
#[no_mangle]
|
/// removed when this function returns. Otherwise, the stack space used for
|
||||||
pub unsafe fn reset_handler() {
|
/// these static_inits is wasted.
|
||||||
// Loads relocations and clears BSS
|
#[inline(never)]
|
||||||
nrf52840::init();
|
unsafe fn get_peripherals() -> &'static mut Nrf52840DefaultPeripherals<'static> {
|
||||||
let ppi = static_init!(nrf52840::ppi::Ppi, nrf52840::ppi::Ppi::new());
|
|
||||||
// Initialize chip peripheral drivers
|
// Initialize chip peripheral drivers
|
||||||
let nrf52840_peripherals = static_init!(
|
let nrf52840_peripherals = static_init!(
|
||||||
Nrf52840DefaultPeripherals,
|
Nrf52840DefaultPeripherals,
|
||||||
Nrf52840DefaultPeripherals::new(ppi)
|
Nrf52840DefaultPeripherals::new()
|
||||||
);
|
);
|
||||||
|
|
||||||
|
nrf52840_peripherals
|
||||||
|
}
|
||||||
|
|
||||||
|
impl KernelResources<nrf52840::chip::NRF52<'static, Nrf52840DefaultPeripherals<'static>>>
|
||||||
|
for Platform
|
||||||
|
{
|
||||||
|
type SyscallDriverLookup = Self;
|
||||||
|
type SyscallFilter = Self;
|
||||||
|
type ProcessFault = ();
|
||||||
|
type Scheduler = RoundRobinSched<'static>;
|
||||||
|
type SchedulerTimer = cortexm4::systick::SysTick;
|
||||||
|
type WatchDog = ();
|
||||||
|
type ContextSwitchCallback = ();
|
||||||
|
|
||||||
|
fn syscall_driver_lookup(&self) -> &Self::SyscallDriverLookup {
|
||||||
|
&self
|
||||||
|
}
|
||||||
|
fn syscall_filter(&self) -> &Self::SyscallFilter {
|
||||||
|
&self
|
||||||
|
}
|
||||||
|
fn process_fault(&self) -> &Self::ProcessFault {
|
||||||
|
&()
|
||||||
|
}
|
||||||
|
fn scheduler(&self) -> &Self::Scheduler {
|
||||||
|
self.scheduler
|
||||||
|
}
|
||||||
|
fn scheduler_timer(&self) -> &Self::SchedulerTimer {
|
||||||
|
&self.systick
|
||||||
|
}
|
||||||
|
fn watchdog(&self) -> &Self::WatchDog {
|
||||||
|
&()
|
||||||
|
}
|
||||||
|
fn context_switch_callback(&self) -> &Self::ContextSwitchCallback {
|
||||||
|
&()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Main function called after RAM initialized.
|
||||||
|
#[no_mangle]
|
||||||
|
pub unsafe fn main() {
|
||||||
|
// Loads relocations and clears BSS
|
||||||
|
nrf52840::init();
|
||||||
|
// Initialize chip peripheral drivers
|
||||||
|
let nrf52840_peripherals = get_peripherals();
|
||||||
|
|
||||||
// set up circular peripheral dependencies
|
// set up circular peripheral dependencies
|
||||||
nrf52840_peripherals.init();
|
nrf52840_peripherals.init();
|
||||||
let base_peripherals = &nrf52840_peripherals.nrf52;
|
let base_peripherals = &nrf52840_peripherals.nrf52;
|
||||||
@@ -249,6 +307,7 @@ pub unsafe fn reset_handler() {
|
|||||||
|
|
||||||
let gpio = components::gpio::GpioComponent::new(
|
let gpio = components::gpio::GpioComponent::new(
|
||||||
board_kernel,
|
board_kernel,
|
||||||
|
capsules::gpio::DRIVER_NUM,
|
||||||
components::gpio_component_helper!(
|
components::gpio_component_helper!(
|
||||||
nrf52840::gpio::GPIOPin,
|
nrf52840::gpio::GPIOPin,
|
||||||
0 => &nrf52840_peripherals.gpio_port[Pin::P1_01],
|
0 => &nrf52840_peripherals.gpio_port[Pin::P1_01],
|
||||||
@@ -273,6 +332,7 @@ pub unsafe fn reset_handler() {
|
|||||||
|
|
||||||
let button = components::button::ButtonComponent::new(
|
let button = components::button::ButtonComponent::new(
|
||||||
board_kernel,
|
board_kernel,
|
||||||
|
capsules::button::DRIVER_NUM,
|
||||||
components::button_component_helper!(
|
components::button_component_helper!(
|
||||||
nrf52840::gpio::GPIOPin,
|
nrf52840::gpio::GPIOPin,
|
||||||
(
|
(
|
||||||
@@ -299,15 +359,12 @@ pub unsafe fn reset_handler() {
|
|||||||
)
|
)
|
||||||
.finalize(components::button_component_buf!(nrf52840::gpio::GPIOPin));
|
.finalize(components::button_component_buf!(nrf52840::gpio::GPIOPin));
|
||||||
|
|
||||||
let led = components::led::LedsComponent::new(components::led_component_helper!(
|
let led = components::led::LedsComponent::new().finalize(components::led_component_helper!(
|
||||||
LedLow<'static, nrf52840::gpio::GPIOPin>,
|
LedLow<'static, nrf52840::gpio::GPIOPin>,
|
||||||
LedLow::new(&nrf52840_peripherals.gpio_port[LED1_PIN]),
|
LedLow::new(&nrf52840_peripherals.gpio_port[LED1_PIN]),
|
||||||
LedLow::new(&nrf52840_peripherals.gpio_port[LED2_PIN]),
|
LedLow::new(&nrf52840_peripherals.gpio_port[LED2_PIN]),
|
||||||
LedLow::new(&nrf52840_peripherals.gpio_port[LED3_PIN]),
|
LedLow::new(&nrf52840_peripherals.gpio_port[LED3_PIN]),
|
||||||
LedLow::new(&nrf52840_peripherals.gpio_port[LED4_PIN]),
|
LedLow::new(&nrf52840_peripherals.gpio_port[LED4_PIN]),
|
||||||
))
|
|
||||||
.finalize(components::led_component_buf!(
|
|
||||||
LedLow<'static, nrf52840::gpio::GPIOPin>
|
|
||||||
));
|
));
|
||||||
|
|
||||||
let chip = static_init!(
|
let chip = static_init!(
|
||||||
@@ -339,10 +396,14 @@ pub unsafe fn reset_handler() {
|
|||||||
);
|
);
|
||||||
|
|
||||||
let rtc = &base_peripherals.rtc;
|
let rtc = &base_peripherals.rtc;
|
||||||
rtc.start();
|
let _ = rtc.start();
|
||||||
let mux_alarm = components::alarm::AlarmMuxComponent::new(rtc)
|
let mux_alarm = components::alarm::AlarmMuxComponent::new(rtc)
|
||||||
.finalize(components::alarm_mux_component_helper!(nrf52840::rtc::Rtc));
|
.finalize(components::alarm_mux_component_helper!(nrf52840::rtc::Rtc));
|
||||||
let alarm = components::alarm::AlarmDriverComponent::new(board_kernel, mux_alarm)
|
let alarm = components::alarm::AlarmDriverComponent::new(
|
||||||
|
board_kernel,
|
||||||
|
capsules::alarm::DRIVER_NUM,
|
||||||
|
mux_alarm,
|
||||||
|
)
|
||||||
.finalize(components::alarm_component_helper!(nrf52840::rtc::Rtc));
|
.finalize(components::alarm_component_helper!(nrf52840::rtc::Rtc));
|
||||||
|
|
||||||
let channel = nrf52_components::UartChannelComponent::new(
|
let channel = nrf52_components::UartChannelComponent::new(
|
||||||
@@ -359,22 +420,41 @@ pub unsafe fn reset_handler() {
|
|||||||
DynamicDeferredCall::new(dynamic_deferred_call_clients)
|
DynamicDeferredCall::new(dynamic_deferred_call_clients)
|
||||||
);
|
);
|
||||||
DynamicDeferredCall::set_global_instance(dynamic_deferred_caller);
|
DynamicDeferredCall::set_global_instance(dynamic_deferred_caller);
|
||||||
|
let process_printer =
|
||||||
|
components::process_printer::ProcessPrinterTextComponent::new().finalize(());
|
||||||
|
PROCESS_PRINTER = Some(process_printer);
|
||||||
|
|
||||||
// Create a shared UART channel for the console and for kernel debug.
|
// Create a shared UART channel for the console and for kernel debug.
|
||||||
let uart_mux =
|
let uart_mux =
|
||||||
components::console::UartMuxComponent::new(channel, 115200, dynamic_deferred_caller)
|
components::console::UartMuxComponent::new(channel, 115200, dynamic_deferred_caller)
|
||||||
.finalize(());
|
.finalize(());
|
||||||
|
|
||||||
let pconsole =
|
let pconsole = components::process_console::ProcessConsoleComponent::new(
|
||||||
components::process_console::ProcessConsoleComponent::new(board_kernel, uart_mux)
|
board_kernel,
|
||||||
.finalize(());
|
uart_mux,
|
||||||
|
mux_alarm,
|
||||||
|
process_printer,
|
||||||
|
)
|
||||||
|
.finalize(components::process_console_component_helper!(
|
||||||
|
nrf52840::rtc::Rtc<'static>
|
||||||
|
));
|
||||||
|
|
||||||
// Setup the console.
|
// Setup the console.
|
||||||
let console = components::console::ConsoleComponent::new(board_kernel, uart_mux).finalize(());
|
let console = components::console::ConsoleComponent::new(
|
||||||
|
board_kernel,
|
||||||
|
capsules::console::DRIVER_NUM,
|
||||||
|
uart_mux,
|
||||||
|
)
|
||||||
|
.finalize(components::console_component_helper!());
|
||||||
// Create the debugger object that handles calls to `debug!()`.
|
// Create the debugger object that handles calls to `debug!()`.
|
||||||
components::debug_writer::DebugWriterComponent::new(uart_mux).finalize(());
|
components::debug_writer::DebugWriterComponent::new(uart_mux).finalize(());
|
||||||
|
|
||||||
let rng = components::rng::RngComponent::new(board_kernel, &base_peripherals.trng).finalize(());
|
let rng = components::rng::RngComponent::new(
|
||||||
|
board_kernel,
|
||||||
|
capsules::rng::DRIVER_NUM,
|
||||||
|
&base_peripherals.trng,
|
||||||
|
)
|
||||||
|
.finalize(());
|
||||||
|
|
||||||
base_peripherals.spim0.configure(
|
base_peripherals.spim0.configure(
|
||||||
nrf52840::pinmux::Pinmux::new(SPI_MOSI as u32),
|
nrf52840::pinmux::Pinmux::new(SPI_MOSI as u32),
|
||||||
@@ -390,6 +470,8 @@ pub unsafe fn reset_handler() {
|
|||||||
nrf52840::acomp::Channel,
|
nrf52840::acomp::Channel,
|
||||||
&nrf52840::acomp::CHANNEL_AC0
|
&nrf52840::acomp::CHANNEL_AC0
|
||||||
),
|
),
|
||||||
|
board_kernel,
|
||||||
|
capsules::analog_comparator::DRIVER_NUM,
|
||||||
)
|
)
|
||||||
.finalize(components::acomp_component_buf!(
|
.finalize(components::acomp_component_buf!(
|
||||||
nrf52840::acomp::Comparator
|
nrf52840::acomp::Comparator
|
||||||
@@ -399,8 +481,9 @@ pub unsafe fn reset_handler() {
|
|||||||
nrf52840::nvmc::SyscallDriver,
|
nrf52840::nvmc::SyscallDriver,
|
||||||
nrf52840::nvmc::SyscallDriver::new(
|
nrf52840::nvmc::SyscallDriver::new(
|
||||||
&base_peripherals.nvmc,
|
&base_peripherals.nvmc,
|
||||||
board_kernel.create_grant(&memory_allocation_capability),
|
board_kernel.create_grant(nrf52840::nvmc::DRIVER_NUM, &memory_allocation_capability),
|
||||||
dynamic_deferred_caller,
|
dynamic_deferred_caller,
|
||||||
|
&mut APP_FLASH_BUFFER,
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
nvmc.set_deferred_handle(
|
nvmc.set_deferred_handle(
|
||||||
@@ -412,21 +495,17 @@ pub unsafe fn reset_handler() {
|
|||||||
// Configure USB controller
|
// Configure USB controller
|
||||||
let usb = components::usb_ctap::UsbCtapComponent::new(
|
let usb = components::usb_ctap::UsbCtapComponent::new(
|
||||||
board_kernel,
|
board_kernel,
|
||||||
|
capsules::usb::usb_ctap::DRIVER_NUM,
|
||||||
&nrf52840_peripherals.usbd,
|
&nrf52840_peripherals.usbd,
|
||||||
capsules::usb::usbc_client::MAX_CTRL_PACKET_SIZE_NRF52840,
|
capsules::usb::usbc_client::MAX_CTRL_PACKET_SIZE_NRF52840,
|
||||||
VENDOR_ID,
|
VENDOR_ID,
|
||||||
PRODUCT_ID,
|
PRODUCT_ID,
|
||||||
STRINGS,
|
STRINGS,
|
||||||
)
|
)
|
||||||
.finalize(components::usb_ctap_component_buf!(nrf52840::usbd::Usbd));
|
.finalize(components::usb_ctap_component_helper!(nrf52840::usbd::Usbd));
|
||||||
|
|
||||||
let crp = components::firmware_protection::FirmwareProtectionComponent::new(
|
let scheduler = components::sched::round_robin::RoundRobinComponent::new(&PROCESSES)
|
||||||
board_kernel,
|
.finalize(components::rr_component_helper!(NUM_PROCS));
|
||||||
nrf52840::uicr::Uicr::new(),
|
|
||||||
)
|
|
||||||
.finalize(components::firmware_protection_component_helper!(
|
|
||||||
nrf52840::uicr::Uicr
|
|
||||||
));
|
|
||||||
|
|
||||||
nrf52_components::NrfClockComponent::new(&base_peripherals.clock).finalize(());
|
nrf52_components::NrfClockComponent::new(&base_peripherals.clock).finalize(());
|
||||||
|
|
||||||
@@ -441,15 +520,20 @@ pub unsafe fn reset_handler() {
|
|||||||
analog_comparator,
|
analog_comparator,
|
||||||
nvmc,
|
nvmc,
|
||||||
usb,
|
usb,
|
||||||
crp,
|
ipc: kernel::ipc::IPC::new(
|
||||||
ipc: kernel::ipc::IPC::new(board_kernel, &memory_allocation_capability),
|
board_kernel,
|
||||||
|
kernel::ipc::DRIVER_NUM,
|
||||||
|
&memory_allocation_capability,
|
||||||
|
),
|
||||||
|
scheduler,
|
||||||
|
systick: cortexm4::systick::SysTick::new_with_calibration(64000000),
|
||||||
};
|
};
|
||||||
|
|
||||||
platform.pconsole.start();
|
let _ = platform.pconsole.start();
|
||||||
debug!("Initialization complete. Entering main loop\r");
|
debug!("Initialization complete. Entering main loop\r");
|
||||||
debug!("{}", &nrf52840::ficr::FICR_INSTANCE);
|
debug!("{}", &nrf52840::ficr::FICR_INSTANCE);
|
||||||
|
|
||||||
/// These symbols are defined in the linker script.
|
// These symbols are defined in the linker script.
|
||||||
extern "C" {
|
extern "C" {
|
||||||
/// Beginning of the ROM region containing app images.
|
/// Beginning of the ROM region containing app images.
|
||||||
static _sapps: u8;
|
static _sapps: u8;
|
||||||
@@ -461,7 +545,7 @@ pub unsafe fn reset_handler() {
|
|||||||
static _eappmem: u8;
|
static _eappmem: u8;
|
||||||
}
|
}
|
||||||
|
|
||||||
kernel::procs::load_processes(
|
kernel::process::load_processes(
|
||||||
board_kernel,
|
board_kernel,
|
||||||
chip,
|
chip,
|
||||||
core::slice::from_raw_parts(
|
core::slice::from_raw_parts(
|
||||||
@@ -473,7 +557,7 @@ pub unsafe fn reset_handler() {
|
|||||||
&_eappmem as *const u8 as usize - &_sappmem as *const u8 as usize,
|
&_eappmem as *const u8 as usize - &_sappmem as *const u8 as usize,
|
||||||
),
|
),
|
||||||
&mut PROCESSES,
|
&mut PROCESSES,
|
||||||
FAULT_RESPONSE,
|
&FAULT_RESPONSE,
|
||||||
&process_management_capability,
|
&process_management_capability,
|
||||||
)
|
)
|
||||||
.unwrap_or_else(|err| {
|
.unwrap_or_else(|err| {
|
||||||
@@ -481,13 +565,5 @@ pub unsafe fn reset_handler() {
|
|||||||
debug!("{:?}", err);
|
debug!("{:?}", err);
|
||||||
});
|
});
|
||||||
|
|
||||||
let scheduler = components::sched::round_robin::RoundRobinComponent::new(&PROCESSES)
|
board_kernel.kernel_loop(&platform, chip, Some(&platform.ipc), &main_loop_capability);
|
||||||
.finalize(components::rr_component_helper!(NUM_PROCS));
|
|
||||||
board_kernel.kernel_loop(
|
|
||||||
&platform,
|
|
||||||
chip,
|
|
||||||
Some(&platform.ipc),
|
|
||||||
scheduler,
|
|
||||||
&main_loop_capability,
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|||||||
56
bootloader/Cargo.lock
generated
56
bootloader/Cargo.lock
generated
@@ -19,7 +19,7 @@ checksum = "45403b49e3954a4b8428a0ac21a4b7afadccf92bfd96273f1a58cd4812496ae0"
|
|||||||
dependencies = [
|
dependencies = [
|
||||||
"generic-array 0.12.4",
|
"generic-array 0.12.4",
|
||||||
"generic-array 0.13.3",
|
"generic-array 0.13.3",
|
||||||
"generic-array 0.14.6",
|
"generic-array 0.14.7",
|
||||||
"stable_deref_trait",
|
"stable_deref_trait",
|
||||||
]
|
]
|
||||||
|
|
||||||
@@ -53,9 +53,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "byteorder"
|
name = "byteorder"
|
||||||
version = "1.4.3"
|
version = "1.5.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "14c189c53d098945499cdfa7ecc63567cf3886b3332b312a5b4585d8d3a6a610"
|
checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "cortex-m"
|
name = "cortex-m"
|
||||||
@@ -66,15 +66,15 @@ dependencies = [
|
|||||||
"aligned",
|
"aligned",
|
||||||
"bare-metal",
|
"bare-metal",
|
||||||
"bitfield",
|
"bitfield",
|
||||||
"cortex-m 0.7.6",
|
"cortex-m 0.7.7",
|
||||||
"volatile-register",
|
"volatile-register",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "cortex-m"
|
name = "cortex-m"
|
||||||
version = "0.7.6"
|
version = "0.7.7"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "70858629a458fdfd39f9675c4dc309411f2a3f83bede76988d81bf1a0ecee9e0"
|
checksum = "8ec610d8f49840a5b376c69663b6369e71f4b34484b9b2eb29fb918d92516cb9"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bare-metal",
|
"bare-metal",
|
||||||
"bitfield",
|
"bitfield",
|
||||||
@@ -84,9 +84,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "cortex-m-rt"
|
name = "cortex-m-rt"
|
||||||
version = "0.7.1"
|
version = "0.7.3"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "3c433da385b720d5bb9f52362fa2782420798e68d40d67bfe4b0d992aba5dfe7"
|
checksum = "ee84e813d593101b1723e13ec38b6ab6abbdbaaa4546553f5395ed274079ddb1"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"cortex-m-rt-macros",
|
"cortex-m-rt-macros",
|
||||||
]
|
]
|
||||||
@@ -132,9 +132,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "generic-array"
|
name = "generic-array"
|
||||||
version = "0.14.6"
|
version = "0.14.7"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "bff49e947297f3312447abdca79f45f4738097cc82b06e72054d2223f601f1b9"
|
checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"typenum",
|
"typenum",
|
||||||
"version_check",
|
"version_check",
|
||||||
@@ -146,14 +146,14 @@ version = "0.1.3"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "801d31da0513b6ec5214e9bf433a77966320625a37860f910be265be6e18d06f"
|
checksum = "801d31da0513b6ec5214e9bf433a77966320625a37860f910be265be6e18d06f"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"nb 1.0.0",
|
"nb 1.1.0",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "nb"
|
name = "nb"
|
||||||
version = "1.0.0"
|
version = "1.1.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "546c37ac5d9e56f55e73b677106873d9d9f5190605e41a856503623648488cae"
|
checksum = "8d5439c4ad607c3c23abf66de8c8bf57ba8adcd1f129e699851a6e43935d339d"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "panic-abort"
|
name = "panic-abort"
|
||||||
@@ -163,18 +163,18 @@ checksum = "4e20e6499bbbc412f280b04a42346b356c6fa0753d5fd22b7bd752ff34c778ee"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "proc-macro2"
|
name = "proc-macro2"
|
||||||
version = "1.0.43"
|
version = "1.0.69"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "0a2ca2c61bc9f3d74d2886294ab7b9853abd9c1ad903a3ac7815c58989bb7bab"
|
checksum = "134c189feb4956b20f6f547d2cf727d4c0fe06722b20a0eec87ed445a97f92da"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"unicode-ident",
|
"unicode-ident",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "quote"
|
name = "quote"
|
||||||
version = "1.0.21"
|
version = "1.0.33"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "bbe448f377a7d6961e30f5955f9b8d106c3f5e449d493ee1b125c1d43c2b5179"
|
checksum = "5267fca4496028628a95160fc423a33e8b2e6af8a5302579e322e4b520293cae"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
]
|
]
|
||||||
@@ -185,7 +185,7 @@ version = "0.3.1"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "065d6058bb1204f51a562a67209e1817cf714759d5cf845aa45c75fa7b0b9d9b"
|
checksum = "065d6058bb1204f51a562a67209e1817cf714759d5cf845aa45c75fa7b0b9d9b"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"cortex-m 0.7.6",
|
"cortex-m 0.7.7",
|
||||||
"ufmt-write",
|
"ufmt-write",
|
||||||
]
|
]
|
||||||
|
|
||||||
@@ -221,9 +221,9 @@ checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "syn"
|
name = "syn"
|
||||||
version = "1.0.100"
|
version = "1.0.109"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "52205623b1b0f064a4e71182c3b18ae902267282930c6d5462c91b859668426e"
|
checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
@@ -232,15 +232,15 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "tock-registers"
|
name = "tock-registers"
|
||||||
version = "0.6.0"
|
version = "0.7.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "f521a79accce68c417c9c77ce22108056b626126da1932f7e2e9b5bbffee0cea"
|
checksum = "4ee8fba06c1f4d0b396ef61a54530bb6b28f0dc61c38bc8bc5a5a48161e6282e"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "typenum"
|
name = "typenum"
|
||||||
version = "1.15.0"
|
version = "1.17.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "dcf81ac59edc17cc8697ff311e8f5ef2d99fcbd9817b34cec66f90b6c3dfd987"
|
checksum = "42ff0bf0c66b8238c6f3b578df37d0b7848e55df8577b3f74f92a69acceeb825"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "ufmt-write"
|
name = "ufmt-write"
|
||||||
@@ -250,9 +250,9 @@ checksum = "e87a2ed6b42ec5e28cc3b94c09982969e9227600b2e3dcbc1db927a84c06bd69"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "unicode-ident"
|
name = "unicode-ident"
|
||||||
version = "1.0.4"
|
version = "1.0.12"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "dcc811dc4066ac62f84f11307873c4850cb653bfa9b1719cee2bd2204a4bc5dd"
|
checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "vcell"
|
name = "vcell"
|
||||||
@@ -274,9 +274,9 @@ checksum = "6a02e4885ed3bc0f2de90ea6dd45ebcbb66dacffe03547fadbb0eeae2770887d"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "volatile-register"
|
name = "volatile-register"
|
||||||
version = "0.2.1"
|
version = "0.2.2"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "9ee8f19f9d74293faf70901bc20ad067dc1ad390d2cbf1e3f75f721ffee908b6"
|
checksum = "de437e2a6208b014ab52972a27e59b33fa2920d3e00fe05026167a1c509d19cc"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"vcell",
|
"vcell",
|
||||||
]
|
]
|
||||||
|
|||||||
@@ -15,7 +15,7 @@ cortex-m-rt = "*"
|
|||||||
cortex-m-rt-macros = "*"
|
cortex-m-rt-macros = "*"
|
||||||
panic-abort = "0.3.2"
|
panic-abort = "0.3.2"
|
||||||
rtt-target = { version = "*", features = ["cortex-m"] }
|
rtt-target = { version = "*", features = ["cortex-m"] }
|
||||||
tock-registers = { version = "0.6.0", features = ["no_std_unit_tests"] }
|
tock-registers = "0.7.0"
|
||||||
|
|
||||||
[profile.dev]
|
[profile.dev]
|
||||||
panic = "abort"
|
panic = "abort"
|
||||||
|
|||||||
@@ -1,4 +0,0 @@
|
|||||||
[toolchain]
|
|
||||||
channel = "nightly-2021-03-25"
|
|
||||||
components = ["clippy", "rustfmt"]
|
|
||||||
targets = ["thumbv7em-none-eabi"]
|
|
||||||
@@ -26,6 +26,7 @@ use super::static_ref::StaticRef;
|
|||||||
use core::cell::Cell;
|
use core::cell::Cell;
|
||||||
#[cfg(debug_assertions)]
|
#[cfg(debug_assertions)]
|
||||||
use rtt_target::rprintln;
|
use rtt_target::rprintln;
|
||||||
|
use tock_registers::interfaces::{Readable, Writeable};
|
||||||
|
|
||||||
const SHA256_INIT_VALUE: [u32; 8] = [
|
const SHA256_INIT_VALUE: [u32; 8] = [
|
||||||
0x6A09E667, 0xBB67AE85, 0x3C6EF372, 0xA54FF53A, 0x510E527F, 0x9B05688C, 0x1F83D9AB, 0x5BE0CD19,
|
0x6A09E667, 0xBB67AE85, 0x3C6EF372, 0xA54FF53A, 0x510E527F, 0x9B05688C, 0x1F83D9AB, 0x5BE0CD19,
|
||||||
|
|||||||
@@ -40,7 +40,7 @@ impl<T> Copy for StaticRef<T> {}
|
|||||||
|
|
||||||
impl<T> Deref for StaticRef<T> {
|
impl<T> Deref for StaticRef<T> {
|
||||||
type Target = T;
|
type Target = T;
|
||||||
fn deref(&self) -> &'static T {
|
fn deref(&self) -> &T {
|
||||||
unsafe { &*self.ptr }
|
unsafe { &*self.ptr }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
6
build.rs
6
build.rs
@@ -24,7 +24,7 @@ use uuid::Uuid;
|
|||||||
fn main() {
|
fn main() {
|
||||||
const UPGRADE_FILE: &str = "crypto_data/opensk_upgrade_pub.pem";
|
const UPGRADE_FILE: &str = "crypto_data/opensk_upgrade_pub.pem";
|
||||||
println!("cargo:rerun-if-changed=crypto_data/aaguid.txt");
|
println!("cargo:rerun-if-changed=crypto_data/aaguid.txt");
|
||||||
println!("cargo:rerun-if-changed={}", UPGRADE_FILE);
|
println!("cargo:rerun-if-changed={UPGRADE_FILE}");
|
||||||
println!("cargo:rerun-if-changed=layout.ld");
|
println!("cargo:rerun-if-changed=layout.ld");
|
||||||
println!("cargo:rerun-if-changed=nrf52840_layout.ld");
|
println!("cargo:rerun-if-changed=nrf52840_layout.ld");
|
||||||
println!("cargo:rerun-if-changed=nrf52840_layout_a.ld");
|
println!("cargo:rerun-if-changed=nrf52840_layout_a.ld");
|
||||||
@@ -33,7 +33,7 @@ fn main() {
|
|||||||
let out_dir = env::var_os("OUT_DIR").unwrap();
|
let out_dir = env::var_os("OUT_DIR").unwrap();
|
||||||
let aaguid_bin_path = Path::new(&out_dir).join("opensk_aaguid.bin");
|
let aaguid_bin_path = Path::new(&out_dir).join("opensk_aaguid.bin");
|
||||||
|
|
||||||
let mut aaguid_bin_file = File::create(&aaguid_bin_path).unwrap();
|
let mut aaguid_bin_file = File::create(aaguid_bin_path).unwrap();
|
||||||
let mut aaguid_txt_file = File::open("crypto_data/aaguid.txt").unwrap();
|
let mut aaguid_txt_file = File::open("crypto_data/aaguid.txt").unwrap();
|
||||||
let mut content = String::new();
|
let mut content = String::new();
|
||||||
aaguid_txt_file.read_to_string(&mut content).unwrap();
|
aaguid_txt_file.read_to_string(&mut content).unwrap();
|
||||||
@@ -52,6 +52,6 @@ fn main() {
|
|||||||
.to_bytes(&group, conversion_form, &mut ctx)
|
.to_bytes(&group, conversion_form, &mut ctx)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
let upgrade_pubkey_path = Path::new(&out_dir).join("opensk_upgrade_pubkey.bin");
|
let upgrade_pubkey_path = Path::new(&out_dir).join("opensk_upgrade_pubkey.bin");
|
||||||
let mut upgrade_pub_bin_file = File::create(&upgrade_pubkey_path).unwrap();
|
let mut upgrade_pub_bin_file = File::create(upgrade_pubkey_path).unwrap();
|
||||||
upgrade_pub_bin_file.write_all(&raw_bytes).unwrap();
|
upgrade_pub_bin_file.write_all(&raw_bytes).unwrap();
|
||||||
}
|
}
|
||||||
|
|||||||
173
deploy.py
173
deploy.py
@@ -1,5 +1,5 @@
|
|||||||
#!/usr/bin/env python3
|
#!py_virtual_env/bin/python3
|
||||||
# Copyright 2019 Google LLC
|
# Copyright 2019-2023 Google LLC
|
||||||
#
|
#
|
||||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
# you may not use this file except in compliance with the License.
|
# you may not use this file except in compliance with the License.
|
||||||
@@ -23,6 +23,7 @@ import argparse
|
|||||||
import collections
|
import collections
|
||||||
import copy
|
import copy
|
||||||
import os
|
import os
|
||||||
|
from serial.tools import list_ports
|
||||||
import shutil
|
import shutil
|
||||||
import subprocess
|
import subprocess
|
||||||
import sys
|
import sys
|
||||||
@@ -156,7 +157,11 @@ SUPPORTED_BOARDS = {
|
|||||||
),
|
),
|
||||||
}
|
}
|
||||||
|
|
||||||
APP_HEAP_SIZE = 32768
|
# The following value must match the one used in the file
|
||||||
|
# `src/entry_point.rs`
|
||||||
|
APP_HEAP_SIZE = 90_000
|
||||||
|
|
||||||
|
CARGO_TARGET_DIR = os.environ.get("CARGO_TARGET_DIR", "target")
|
||||||
|
|
||||||
|
|
||||||
def get_supported_boards() -> Tuple[str]:
|
def get_supported_boards() -> Tuple[str]:
|
||||||
@@ -198,6 +203,12 @@ def assert_python_library(module: str):
|
|||||||
f"Try to run: pip3 install {module}"))
|
f"Try to run: pip3 install {module}"))
|
||||||
|
|
||||||
|
|
||||||
|
def list_serials(vid: int, pid: int) -> List[str]:
|
||||||
|
ports = list_ports.comports()
|
||||||
|
ports = filter(lambda p: p.vid == vid and p.pid == pid, ports)
|
||||||
|
return list(map(lambda p: p.serial_number, ports))
|
||||||
|
|
||||||
|
|
||||||
class RemoveConstAction(argparse.Action):
|
class RemoveConstAction(argparse.Action):
|
||||||
|
|
||||||
# pylint: disable=redefined-builtin
|
# pylint: disable=redefined-builtin
|
||||||
@@ -252,7 +263,7 @@ class OpenSKInstaller:
|
|||||||
def __init__(self, args):
|
def __init__(self, args):
|
||||||
self.args = args
|
self.args = args
|
||||||
# Where all the TAB files should go
|
# Where all the TAB files should go
|
||||||
self.tab_folder = os.path.join("target", "tab")
|
self.tab_folder = os.path.join(CARGO_TARGET_DIR, "tab")
|
||||||
board = SUPPORTED_BOARDS[self.args.board]
|
board = SUPPORTED_BOARDS[self.args.board]
|
||||||
self.tockloader_default_args = argparse.Namespace(
|
self.tockloader_default_args = argparse.Namespace(
|
||||||
app_address=board.app_address,
|
app_address=board.app_address,
|
||||||
@@ -318,46 +329,6 @@ class OpenSKInstaller:
|
|||||||
# Unreachable because fatal() will exit
|
# Unreachable because fatal() will exit
|
||||||
return cmd_output.decode()
|
return cmd_output.decode()
|
||||||
|
|
||||||
def update_rustc_if_needed(self):
|
|
||||||
"""Updates the Rust and installs the necessary target toolchain."""
|
|
||||||
target_toolchain_fullstring = "stable"
|
|
||||||
with open("rust-toolchain", "r", encoding="utf-8") as f:
|
|
||||||
content = f.readlines()
|
|
||||||
if len(content) == 1:
|
|
||||||
# Old format, only the build is stored
|
|
||||||
target_toolchain_fullstring = content[0].strip()
|
|
||||||
else:
|
|
||||||
# New format
|
|
||||||
for line in content:
|
|
||||||
if line.startswith("channel"):
|
|
||||||
channel = line.strip().split("=", maxsplit=1)[1].strip()
|
|
||||||
target_toolchain_fullstring = channel.strip('"')
|
|
||||||
target_toolchain = target_toolchain_fullstring.split("-", maxsplit=1)
|
|
||||||
if len(target_toolchain) == 1:
|
|
||||||
# If we target the stable version of rust, we won't have a date
|
|
||||||
# associated to the version and split will only return 1 item.
|
|
||||||
# To avoid failing later when accessing the date, we insert an
|
|
||||||
# empty value.
|
|
||||||
target_toolchain.append("")
|
|
||||||
current_version = self.checked_command_output(["rustc", "--version"])
|
|
||||||
if not (target_toolchain[0] in current_version and
|
|
||||||
target_toolchain[1] in current_version):
|
|
||||||
info(f"Updating rust toolchain to {'-'.join(target_toolchain)}")
|
|
||||||
# Need to update
|
|
||||||
rustup_install = ["rustup"]
|
|
||||||
if self.args.verbose_build:
|
|
||||||
rustup_install.append("--verbose")
|
|
||||||
rustup_install.extend(["install", target_toolchain_fullstring])
|
|
||||||
self.checked_command(rustup_install)
|
|
||||||
|
|
||||||
rustup_target = ["rustup"]
|
|
||||||
if self.args.verbose_build:
|
|
||||||
rustup_target.append("--verbose")
|
|
||||||
rustup_target.extend(
|
|
||||||
["target", "add", SUPPORTED_BOARDS[self.args.board].arch])
|
|
||||||
self.checked_command(rustup_target)
|
|
||||||
info("Rust toolchain up-to-date")
|
|
||||||
|
|
||||||
def build_tockos(self):
|
def build_tockos(self):
|
||||||
"""Buids Tock OS with the parameters specified in args."""
|
"""Buids Tock OS with the parameters specified in args."""
|
||||||
info(f"Building Tock OS for board {self.args.board}")
|
info(f"Building Tock OS for board {self.args.board}")
|
||||||
@@ -399,7 +370,8 @@ class OpenSKInstaller:
|
|||||||
env["RUSTFLAGS"] = " ".join(rust_flags)
|
env["RUSTFLAGS"] = " ".join(rust_flags)
|
||||||
cargo_command = ["cargo", "build", "--release", f"--target={props.arch}"]
|
cargo_command = ["cargo", "build", "--release", f"--target={props.arch}"]
|
||||||
self.checked_command(cargo_command, cwd="bootloader", env=env)
|
self.checked_command(cargo_command, cwd="bootloader", env=env)
|
||||||
binary_path = os.path.join("target", props.arch, "release", "bootloader")
|
binary_path = os.path.join(CARGO_TARGET_DIR, props.arch, "release",
|
||||||
|
"bootloader")
|
||||||
objcopy_command = [
|
objcopy_command = [
|
||||||
"llvm-objcopy", "-O", "binary", binary_path, f"{binary_path}.bin"
|
"llvm-objcopy", "-O", "binary", binary_path, f"{binary_path}.bin"
|
||||||
]
|
]
|
||||||
@@ -461,7 +433,7 @@ class OpenSKInstaller:
|
|||||||
if self.args.verbose_build:
|
if self.args.verbose_build:
|
||||||
command.append("--verbose")
|
command.append("--verbose")
|
||||||
self.checked_command(command, env=env)
|
self.checked_command(command, env=env)
|
||||||
app_path = os.path.join("target", props.arch, "release")
|
app_path = os.path.join(CARGO_TARGET_DIR, props.arch, "release")
|
||||||
if is_example:
|
if is_example:
|
||||||
app_path = os.path.join(app_path, "examples")
|
app_path = os.path.join(app_path, "examples")
|
||||||
app_path = os.path.join(app_path, self.args.application)
|
app_path = os.path.join(app_path, self.args.application)
|
||||||
@@ -497,14 +469,16 @@ class OpenSKInstaller:
|
|||||||
elf2tab_ver = self.checked_command_output(
|
elf2tab_ver = self.checked_command_output(
|
||||||
["elf2tab/bin/elf2tab", "--version"]).split(
|
["elf2tab/bin/elf2tab", "--version"]).split(
|
||||||
"\n", maxsplit=1)[0]
|
"\n", maxsplit=1)[0]
|
||||||
if elf2tab_ver != "elf2tab 0.7.0":
|
if elf2tab_ver != "elf2tab 0.10.2":
|
||||||
error(("Detected unsupported elf2tab version {elf2tab_ver!a}. The "
|
error(("Detected unsupported elf2tab version {elf2tab_ver!a}! The "
|
||||||
"following commands may fail. Please use 0.7.0 instead."))
|
"following commands may fail. Please use 0.10.2 instead."))
|
||||||
os.makedirs(self.tab_folder, exist_ok=True)
|
os.makedirs(self.tab_folder, exist_ok=True)
|
||||||
tab_filename = os.path.join(self.tab_folder, f"{self.args.application}.tab")
|
tab_filename = os.path.join(self.tab_folder, f"{self.args.application}.tab")
|
||||||
|
supported_kernel = (2, 1)
|
||||||
elf2tab_args = [
|
elf2tab_args = [
|
||||||
"elf2tab/bin/elf2tab", "--deterministic", "--package-name",
|
"elf2tab/bin/elf2tab", "--deterministic", "--package-name",
|
||||||
self.args.application, "-o", tab_filename
|
self.args.application, f"--kernel-major={supported_kernel[0]}",
|
||||||
|
f"--kernel-minor={supported_kernel[1]}", "-o", tab_filename
|
||||||
]
|
]
|
||||||
if self.args.verbose_build:
|
if self.args.verbose_build:
|
||||||
elf2tab_args.append("--verbose")
|
elf2tab_args.append("--verbose")
|
||||||
@@ -522,10 +496,11 @@ class OpenSKInstaller:
|
|||||||
stack_sizes.add(required_stack_size)
|
stack_sizes.add(required_stack_size)
|
||||||
if len(stack_sizes) != 1:
|
if len(stack_sizes) != 1:
|
||||||
error("Detected different stack sizes across tab files.")
|
error("Detected different stack sizes across tab files.")
|
||||||
|
# `protected-region-size` must match the `TBF_HEADER_SIZE`
|
||||||
|
# (currently 0x60 = 96 bytes)
|
||||||
elf2tab_args.extend([
|
elf2tab_args.extend([
|
||||||
f"--stack={stack_sizes.pop()}", f"--app-heap={APP_HEAP_SIZE}",
|
f"--stack={stack_sizes.pop()}", f"--app-heap={APP_HEAP_SIZE}",
|
||||||
"--kernel-heap=1024", "--protected-region-size=64"
|
"--kernel-heap=1024", "--protected-region-size=96"
|
||||||
])
|
])
|
||||||
if self.args.elf2tab_output:
|
if self.args.elf2tab_output:
|
||||||
output = self.checked_command_output(elf2tab_args)
|
output = self.checked_command_output(elf2tab_args)
|
||||||
@@ -606,7 +581,7 @@ class OpenSKInstaller:
|
|||||||
return
|
return
|
||||||
|
|
||||||
kernel = self.read_kernel()
|
kernel = self.read_kernel()
|
||||||
app_tab_path = "target/tab/ctap2.tab"
|
app_tab_path = f"{CARGO_TARGET_DIR}/tab/ctap2.tab"
|
||||||
if not os.path.exists(app_tab_path):
|
if not os.path.exists(app_tab_path):
|
||||||
fatal(f"File not found: {app_tab_path}")
|
fatal(f"File not found: {app_tab_path}")
|
||||||
app_tab = tab.TAB(app_tab_path)
|
app_tab = tab.TAB(app_tab_path)
|
||||||
@@ -700,17 +675,18 @@ class OpenSKInstaller:
|
|||||||
final_hex.merge(padding_hex, overlap="error")
|
final_hex.merge(padding_hex, overlap="error")
|
||||||
|
|
||||||
# Now we can add the application from the TAB file
|
# Now we can add the application from the TAB file
|
||||||
app_tab_path = f"target/tab/{self.args.application}.tab"
|
app_tab_path = f"{CARGO_TARGET_DIR}/tab/{self.args.application}.tab"
|
||||||
assert os.path.exists(app_tab_path)
|
assert os.path.exists(app_tab_path)
|
||||||
app_tab = tab.TAB(app_tab_path)
|
app_tab = tab.TAB(app_tab_path)
|
||||||
if board_props.arch not in app_tab.get_supported_architectures():
|
if board_props.arch not in app_tab.get_supported_architectures():
|
||||||
fatal(("It seems that the TAB file was not produced for the "
|
fatal(("It seems that the TAB file was not produced for the "
|
||||||
"architecture {board_props.arch}"))
|
"architecture {board_props.arch}"))
|
||||||
app_hex = intelhex.IntelHex()
|
app_hex = intelhex.IntelHex()
|
||||||
app_hex.frombytes(
|
tab_bytes = app_tab.extract_app(board_props.arch).get_binary(
|
||||||
app_tab.extract_app(board_props.arch).get_binary(
|
board_props.app_address)
|
||||||
board_props.app_address),
|
if tab_bytes is None:
|
||||||
offset=board_props.app_address)
|
fatal("The extracted bytes from the TAB file are none")
|
||||||
|
app_hex.frombytes(tab_bytes, offset=board_props.app_address)
|
||||||
final_hex.merge(app_hex)
|
final_hex.merge(app_hex)
|
||||||
info(f"Generating all-merged HEX file: {dest_file}")
|
info(f"Generating all-merged HEX file: {dest_file}")
|
||||||
final_hex.tofile(dest_file, format="hex")
|
final_hex.tofile(dest_file, format="hex")
|
||||||
@@ -734,13 +710,14 @@ class OpenSKInstaller:
|
|||||||
fatal("This board doesn't seem to support flashing through pyocd.")
|
fatal("This board doesn't seem to support flashing through pyocd.")
|
||||||
|
|
||||||
if self.args.programmer == "nordicdfu":
|
if self.args.programmer == "nordicdfu":
|
||||||
assert_mandatory_binary("nrfutil")
|
|
||||||
assert_python_library("intelhex")
|
assert_python_library("intelhex")
|
||||||
assert_python_library("nordicsemi.lister")
|
assert_mandatory_binary("nrfutil")
|
||||||
nrfutil_version = __import__("nordicsemi.version").version.NRFUTIL_VERSION
|
nrfutil_version = self.checked_command_output(["nrfutil", "version"])
|
||||||
|
nrfutil_version = nrfutil_version.removeprefix("nrfutil version ")
|
||||||
if not nrfutil_version.startswith("6."):
|
if not nrfutil_version.startswith("6."):
|
||||||
fatal(("You need to install nrfutil python3 package v6.0 or above. "
|
fatal(("You need to install nrfutil python3 package v6.0 or above. "
|
||||||
"Found: {nrfutil_version}"))
|
f"Found: v{nrfutil_version}. If you use Python >= 3.11, please "
|
||||||
|
"try version 3.10."))
|
||||||
if not SUPPORTED_BOARDS[self.args.board].nordic_dfu:
|
if not SUPPORTED_BOARDS[self.args.board].nordic_dfu:
|
||||||
fatal("This board doesn't support flashing over DFU.")
|
fatal("This board doesn't support flashing over DFU.")
|
||||||
|
|
||||||
@@ -764,7 +741,6 @@ class OpenSKInstaller:
|
|||||||
def run(self) -> int:
|
def run(self) -> int:
|
||||||
"""Reads args to decide and run all required tasks."""
|
"""Reads args to decide and run all required tasks."""
|
||||||
self.check_prerequisites()
|
self.check_prerequisites()
|
||||||
self.update_rustc_if_needed()
|
|
||||||
|
|
||||||
if not (self.args.tockos or self.args.application or
|
if not (self.args.tockos or self.args.application or
|
||||||
self.args.clear_storage or self.args.configure):
|
self.args.clear_storage or self.args.configure):
|
||||||
@@ -789,6 +765,7 @@ class OpenSKInstaller:
|
|||||||
info("No application selected.")
|
info("No application selected.")
|
||||||
else:
|
else:
|
||||||
self.build_example()
|
self.build_example()
|
||||||
|
self.args.configure = False
|
||||||
|
|
||||||
# Erase persistent storage
|
# Erase persistent storage
|
||||||
if self.args.clear_storage:
|
if self.args.clear_storage:
|
||||||
@@ -808,7 +785,8 @@ class OpenSKInstaller:
|
|||||||
# Install padding and application if needed
|
# Install padding and application if needed
|
||||||
if self.args.application:
|
if self.args.application:
|
||||||
self.install_padding()
|
self.install_padding()
|
||||||
self.install_tab_file(f"target/tab/{self.args.application}.tab")
|
self.install_tab_file(
|
||||||
|
f"{CARGO_TARGET_DIR}/tab/{self.args.application}.tab")
|
||||||
self.install_metadata()
|
self.install_metadata()
|
||||||
if not self.verify_flashed_app(self.args.application):
|
if not self.verify_flashed_app(self.args.application):
|
||||||
error(("It seems that something went wrong. App/example not found "
|
error(("It seems that something went wrong. App/example not found "
|
||||||
@@ -817,8 +795,8 @@ class OpenSKInstaller:
|
|||||||
return 1
|
return 1
|
||||||
|
|
||||||
elif self.args.programmer in ("pyocd", "nordicdfu", "none"):
|
elif self.args.programmer in ("pyocd", "nordicdfu", "none"):
|
||||||
dest_file = f"target/{self.args.board}_merged.hex"
|
dest_file = f"{CARGO_TARGET_DIR}/{self.args.board}_merged.hex"
|
||||||
os.makedirs("target", exist_ok=True)
|
os.makedirs(CARGO_TARGET_DIR, exist_ok=True)
|
||||||
self.create_hex_file(dest_file)
|
self.create_hex_file(dest_file)
|
||||||
|
|
||||||
if self.args.programmer == "pyocd":
|
if self.args.programmer == "pyocd":
|
||||||
@@ -829,7 +807,7 @@ class OpenSKInstaller:
|
|||||||
])
|
])
|
||||||
if self.args.programmer == "nordicdfu":
|
if self.args.programmer == "nordicdfu":
|
||||||
info("Creating DFU package")
|
info("Creating DFU package")
|
||||||
dfu_pkg_file = f"target/{self.args.board}_dfu.zip"
|
dfu_pkg_file = f"{CARGO_TARGET_DIR}/{self.args.board}_dfu.zip"
|
||||||
self.checked_command([
|
self.checked_command([
|
||||||
"nrfutil", "pkg", "generate", "--hw-version=52", "--sd-req=0",
|
"nrfutil", "pkg", "generate", "--hw-version=52", "--sd-req=0",
|
||||||
"--application-version=1", f"--application={dest_file}",
|
"--application-version=1", f"--application={dest_file}",
|
||||||
@@ -841,22 +819,17 @@ class OpenSKInstaller:
|
|||||||
info("Press [ENTER] when ready.")
|
info("Press [ENTER] when ready.")
|
||||||
_ = input()
|
_ = input()
|
||||||
# Search for the DFU devices
|
# Search for the DFU devices
|
||||||
serial_number = []
|
serial_numbers = list_serials(0x1915, 0x521F)
|
||||||
# pylint: disable=g-import-not-at-top,import-outside-toplevel
|
if not serial_numbers:
|
||||||
from nordicsemi.lister import device_lister
|
|
||||||
for device in device_lister.DeviceLister().enumerate():
|
|
||||||
if device.vendor_id == "1915" and device.product_id == "521F":
|
|
||||||
serial_number.append(device.serial_number)
|
|
||||||
if not serial_number:
|
|
||||||
fatal("Couldn't find any DFU device on your system.")
|
fatal("Couldn't find any DFU device on your system.")
|
||||||
if len(serial_number) > 1:
|
if len(serial_numbers) > 1:
|
||||||
fatal("Multiple DFU devices are detected. Please only connect one.")
|
fatal("Multiple DFU devices are detected. Please only connect one.")
|
||||||
# Run the command without capturing stdout so that we show progress
|
# Run the command without capturing stdout so that we show progress
|
||||||
info("Flashing device using DFU...")
|
info("Flashing device using DFU...")
|
||||||
dfu_return_code = subprocess.run(
|
dfu_return_code = subprocess.run(
|
||||||
[
|
[
|
||||||
"nrfutil", "dfu", "usb-serial", f"--package={dfu_pkg_file}",
|
"nrfutil", "dfu", "usb-serial", f"--package={dfu_pkg_file}",
|
||||||
f"--serial-number={serial_number[0]}"
|
f"--serial-number={serial_numbers[0]}"
|
||||||
],
|
],
|
||||||
check=False,
|
check=False,
|
||||||
timeout=None,
|
timeout=None,
|
||||||
@@ -881,6 +854,18 @@ class OpenSKInstaller:
|
|||||||
self.configure()
|
self.configure()
|
||||||
return 0
|
return 0
|
||||||
|
|
||||||
|
def print_configure_help(self):
|
||||||
|
vendor_hid = " --vendor-hid" if "vendor_hid" in self.args.features else ""
|
||||||
|
info("Your device is not yet configured, and lacks some functionality. "
|
||||||
|
"You can check its configuration status with:\n\n"
|
||||||
|
f"./tools/configure.py{vendor_hid}\n\n"
|
||||||
|
"If you run into issues, this command might help:\n\n"
|
||||||
|
f"./tools/configure.py{vendor_hid} \\\n"
|
||||||
|
" --certificate=crypto_data/opensk_cert.pem \\\n"
|
||||||
|
" --private-key=crypto_data/opensk.key\n\n"
|
||||||
|
"Please read the Certificate considerations in docs/customization.md"
|
||||||
|
" to understand the privacy trade-off.")
|
||||||
|
|
||||||
def configure(self):
|
def configure(self):
|
||||||
info("Configuring device.")
|
info("Configuring device.")
|
||||||
# Trying to check or configure the device. Booting might take some time.
|
# Trying to check or configure the device. Booting might take some time.
|
||||||
@@ -892,6 +877,7 @@ class OpenSKInstaller:
|
|||||||
break
|
break
|
||||||
|
|
||||||
if not devices:
|
if not devices:
|
||||||
|
self.print_configure_help()
|
||||||
fatal("No device to configure found.")
|
fatal("No device to configure found.")
|
||||||
status = self.configure_device()
|
status = self.configure_device()
|
||||||
if not status:
|
if not status:
|
||||||
@@ -900,13 +886,7 @@ class OpenSKInstaller:
|
|||||||
if status["cert"] and status["pkey"]:
|
if status["cert"] and status["pkey"]:
|
||||||
info("You're all set!")
|
info("You're all set!")
|
||||||
else:
|
else:
|
||||||
info("Your device is not yet configured, and lacks some functionality. "
|
self.print_configure_help()
|
||||||
"If you run into issues, this command might help:\n\n"
|
|
||||||
"./tools/configure.py \\\n"
|
|
||||||
" --certificate=crypto_data/opensk_cert.pem \\\n"
|
|
||||||
" --private-key=crypto_data/opensk.key\n\n"
|
|
||||||
"Please read the Certificate considerations in docs/customization.md"
|
|
||||||
" to understand the privacy trade-off.")
|
|
||||||
return 0
|
return 0
|
||||||
|
|
||||||
|
|
||||||
@@ -975,7 +955,8 @@ if __name__ == "__main__":
|
|||||||
dest="lock_device",
|
dest="lock_device",
|
||||||
help=("Try to disable JTAG at the end of the operations. This "
|
help=("Try to disable JTAG at the end of the operations. This "
|
||||||
"operation may fail if the device is already locked or if "
|
"operation may fail if the device is already locked or if "
|
||||||
"the certificate/private key are not programmed."),
|
"the certificate/private key are not programmed."
|
||||||
|
"Currently not implemented on nrf52840 and always fails."),
|
||||||
)
|
)
|
||||||
main_parser.add_argument(
|
main_parser.add_argument(
|
||||||
"--inject-certificate",
|
"--inject-certificate",
|
||||||
@@ -1071,6 +1052,20 @@ if __name__ == "__main__":
|
|||||||
help=("Compiles the OpenSK application without backward compatible "
|
help=("Compiles the OpenSK application without backward compatible "
|
||||||
"support for U2F/CTAP1 protocol."),
|
"support for U2F/CTAP1 protocol."),
|
||||||
)
|
)
|
||||||
|
main_parser.add_argument(
|
||||||
|
"--no-config-command",
|
||||||
|
action=RemoveConstAction,
|
||||||
|
const="config_command",
|
||||||
|
dest="features",
|
||||||
|
help=("Removes the AuthenticatorConfig command."),
|
||||||
|
)
|
||||||
|
main_parser.add_argument(
|
||||||
|
"--rust-crypto",
|
||||||
|
action="append_const",
|
||||||
|
const="rust_crypto",
|
||||||
|
dest="features",
|
||||||
|
help=("Compiles the OpenSK application with RustCrypto implementations."),
|
||||||
|
)
|
||||||
main_parser.add_argument(
|
main_parser.add_argument(
|
||||||
"--nfc",
|
"--nfc",
|
||||||
action="append_const",
|
action="append_const",
|
||||||
@@ -1147,14 +1142,14 @@ if __name__ == "__main__":
|
|||||||
help=("Firmware version that is built."),
|
help=("Firmware version that is built."),
|
||||||
)
|
)
|
||||||
|
|
||||||
main_parser.set_defaults(features=["with_ctap1"])
|
main_parser.set_defaults(features=["with_ctap1", "config_command"])
|
||||||
|
|
||||||
# Start parsing to know if we're going to list things or not.
|
# Start parsing to know if we're going to list things or not.
|
||||||
partial_args, _ = main_parser.parse_known_args()
|
partial_args, _ = main_parser.parse_known_args()
|
||||||
|
|
||||||
# We only need the apps_group if we have a board set
|
# We only need the apps_group if we have a board set
|
||||||
apps_group = main_parser.add_mutually_exclusive_group(
|
apps_group = main_parser.add_mutually_exclusive_group(
|
||||||
required=(partial_args.board is not None))
|
required=partial_args.board is not None)
|
||||||
apps_group.add_argument(
|
apps_group.add_argument(
|
||||||
"--no-app",
|
"--no-app",
|
||||||
dest="application",
|
dest="application",
|
||||||
@@ -1175,12 +1170,6 @@ if __name__ == "__main__":
|
|||||||
const="crypto_bench",
|
const="crypto_bench",
|
||||||
help=("Compiles and installs the crypto_bench example that benchmarks "
|
help=("Compiles and installs the crypto_bench example that benchmarks "
|
||||||
"the performance of the cryptographic algorithms on the board."))
|
"the performance of the cryptographic algorithms on the board."))
|
||||||
apps_group.add_argument(
|
|
||||||
"--measure_stack",
|
|
||||||
dest="application",
|
|
||||||
action="store_const",
|
|
||||||
const="measure_stack",
|
|
||||||
help=("Measures stack usage of Dilithium."))
|
|
||||||
apps_group.add_argument(
|
apps_group.add_argument(
|
||||||
"--store_latency",
|
"--store_latency",
|
||||||
dest="application",
|
dest="application",
|
||||||
|
|||||||
@@ -19,6 +19,9 @@ customize it.
|
|||||||
|
|
||||||
### Flashing using DFU (preferred method)
|
### Flashing using DFU (preferred method)
|
||||||
|
|
||||||
|
You need `nrfutil` version 6. The [install manual](../install.md) has
|
||||||
|
setup instructions.
|
||||||
|
|
||||||
To flash the firmware, run:
|
To flash the firmware, run:
|
||||||
|
|
||||||
```shell
|
```shell
|
||||||
|
|||||||
@@ -19,7 +19,7 @@ After general setup, you still need these steps:
|
|||||||
1. Run the script:
|
1. Run the script:
|
||||||
|
|
||||||
```shell
|
```shell
|
||||||
python3 uf2conv.py -c -f 0xada52840 -o target/opensk.uf2 target/nrf52840_mdk_dfu_merged.hex
|
py_virtual_env/bin/python3 uf2conv.py -c -f 0xada52840 -o target/opensk.uf2 target/nrf52840_mdk_dfu_merged.hex
|
||||||
```
|
```
|
||||||
|
|
||||||
1. Boot into DFU mode. Keep the user button pressed on your hardware while
|
1. Boot into DFU mode. Keep the user button pressed on your hardware while
|
||||||
|
|||||||
@@ -62,19 +62,24 @@ firmware. You can bootstrap an upgradable board using one of the two commands:
|
|||||||
Afterwards, you can upgrade the other partition with
|
Afterwards, you can upgrade the other partition with
|
||||||
|
|
||||||
```shell
|
```shell
|
||||||
./tools/perform_upgrade.sh nrf52840dk_opensk_b --version=1
|
# Board A -> B
|
||||||
./tools/perform_upgrade.sh nrf52840dk_opensk_a --version=1
|
./deploy.py --board=nrf52840dk_opensk_b --opensk --programmer=none --version=1
|
||||||
|
py_virtual_env/bin/python3 -m tools.deploy_partition --board=nrf52840dk_opensk_b --version=1
|
||||||
|
# Board B -> A
|
||||||
|
./deploy.py --board=nrf52840dk_opensk_a --opensk --programmer=none --version=1
|
||||||
|
py_virtual_env/bin/python3 -m tools.deploy_partition --board=nrf52840dk_opensk_a --version=1
|
||||||
```
|
```
|
||||||
|
|
||||||
respectively. You can only upgrade the partition that is not currently running,
|
respectively. You can only upgrade the partition that is not currently running,
|
||||||
so always alternate your calls to `perform_upgrade.sh`. Otherwise, this script
|
otherwise your deploy attempts will fail. You can call `deploy_partition` after
|
||||||
works like `deploy.py`. You can call it even after you locked down your device,
|
you locked down your device, to deploy changes to your development board.
|
||||||
to deploy changes to your development board.
|
Upgrades only apply after a reboot.
|
||||||
|
|
||||||
If you deploy with `--vendor-hid`, also add this flag to `perform_upgrade.sh`,
|
If you want to use Vendor HID, add the `--vendor-hid` flag to all calls,
|
||||||
for example:
|
for example:
|
||||||
|
|
||||||
```shell
|
```shell
|
||||||
./deploy.py --board=nrf52840dk_opensk_a --opensk --version=0 --vendor-hid
|
./deploy.py --board=nrf52840dk_opensk_a --opensk --version=0 --vendor-hid
|
||||||
./tools/perform_upgrade.sh nrf52840dk_opensk_b --version=1 --vendor-hid
|
./deploy.py --board=nrf52840dk_opensk_b --opensk --programmer=none --version=1 --vendor-hid
|
||||||
|
py_virtual_env/bin/python3 -m tools.deploy_partition --board=nrf52840dk_opensk_b --version=1 --vendor-hid
|
||||||
```
|
```
|
||||||
|
|||||||
@@ -7,18 +7,18 @@
|
|||||||
All the generated certificates and private keys are stored in the directory
|
All the generated certificates and private keys are stored in the directory
|
||||||
`crypto_data/`. The expected content after running our `setup.sh` script is:
|
`crypto_data/`. The expected content after running our `setup.sh` script is:
|
||||||
|
|
||||||
File | Purpose
|
| File | Purpose |
|
||||||
------------------------ | --------------------------------------------------------
|
| ------------------------ | ----------------------------------------------- |
|
||||||
`aaguid.txt` | Text file containaing the AAGUID value
|
| `aaguid.txt` | Text file containaing the AAGUID value |
|
||||||
`opensk_ca.csr` | Certificate sign request for the Root CA
|
| `opensk_ca.csr` | Certificate sign request for the Root CA |
|
||||||
`opensk_ca.key` | ECC secp256r1 private key used for the Root CA
|
| `opensk_ca.key` | ECC secp256r1 private key used for the Root CA |
|
||||||
`opensk_ca.pem` | PEM encoded certificate of the Root CA
|
| `opensk_ca.pem` | PEM encoded certificate of the Root CA |
|
||||||
`opensk_ca.srl` | File generated by OpenSSL
|
| `opensk_ca.srl` | File generated by OpenSSL |
|
||||||
`opensk_cert.csr` | Certificate sign request for the attestation certificate
|
| `opensk_cert.csr` | CSR for attestation certificate |
|
||||||
`opensk_cert.pem` | PEM encoded certificate used for the authenticator
|
| `opensk_cert.pem` | PEM encoded certificate for the authenticator |
|
||||||
`opensk.key` | ECC secp256r1 private key used for the autenticator
|
| `opensk.key` | ECC secp256r1 private key for the autenticator |
|
||||||
`opensk_upgrade.key` | Private key for signing upgrades through CTAP
|
| `opensk_upgrade.key` | Private key for signing upgrades through CTAP |
|
||||||
`opensk_upgrade_pub.pem` | Public key added to the firmware for verifying upgrades
|
| `opensk_upgrade_pub.pem` | Public key for verifying upgrades |
|
||||||
|
|
||||||
If you want to use your own attestation certificate and private key,
|
If you want to use your own attestation certificate and private key,
|
||||||
replace the `opensk_cert.pem` and `opensk.key` files. The script at
|
replace the `opensk_cert.pem` and `opensk.key` files. The script at
|
||||||
@@ -85,7 +85,7 @@ OpenSK is fuzzed with the [OSS-Fuzz](https://github.com/google/oss-fuzz)
|
|||||||
project. You can also run fuzzing locally. First install:
|
project. You can also run fuzzing locally. First install:
|
||||||
|
|
||||||
```shell
|
```shell
|
||||||
cargo +stable install cargo-fuzz --version 0.10.2
|
./fuzzing_setup.sh
|
||||||
```
|
```
|
||||||
|
|
||||||
Then choose a fuzz target from `fuzz/fuzz_targets/`, e.g.:
|
Then choose a fuzz target from `fuzz/fuzz_targets/`, e.g.:
|
||||||
|
|||||||
@@ -107,31 +107,3 @@ alloc[256, 1] = 0x2002401c (2 ptrs, 384 bytes)
|
|||||||
# After this operation, 1 pointers are allocated, totalling 512 bytes.
|
# After this operation, 1 pointers are allocated, totalling 512 bytes.
|
||||||
dealloc[64, 1] = 0x2002410c (1 ptrs, 512 bytes)
|
dealloc[64, 1] = 0x2002410c (1 ptrs, 512 bytes)
|
||||||
```
|
```
|
||||||
|
|
||||||
A tool is provided to analyze such reports, in `tools/heapviz`. This tool
|
|
||||||
parses the console output, identifies the lines corresponding to (de)allocation
|
|
||||||
operations, and first computes some statistics:
|
|
||||||
|
|
||||||
* Address range used by the heap over this run of the program,
|
|
||||||
* Peak heap usage (how many useful bytes are allocated),
|
|
||||||
* Peak heap consumption (how many bytes are used by the heap, including
|
|
||||||
unavailable bytes between allocated blocks, due to alignment constraints and
|
|
||||||
memory fragmentation),
|
|
||||||
* Fragmentation overhead (difference between heap consumption and usage).
|
|
||||||
|
|
||||||
Then, the `heapviz` tool displays an animated "movie" of the allocated bytes in
|
|
||||||
heap memory. Each frame in this "movie" shows bytes that are currently
|
|
||||||
allocated, that were allocated but are now freed, and that have never been
|
|
||||||
allocated. A new frame is generated for each (de)allocation operation. This tool
|
|
||||||
uses the `ncurses` library, that you may have to install beforehand.
|
|
||||||
|
|
||||||
You can control the tool with the following parameters:
|
|
||||||
|
|
||||||
* `--logfile` (required) to provide the file which contains the console output
|
|
||||||
to parse,
|
|
||||||
* `--fps` (optional) to customize the number of frames per second in the movie
|
|
||||||
animation.
|
|
||||||
|
|
||||||
```shell
|
|
||||||
cargo run --manifest-path tools/heapviz/Cargo.toml -- --logfile console.log --fps 50
|
|
||||||
```
|
|
||||||
|
|||||||
@@ -25,10 +25,10 @@ following:
|
|||||||
* python3 and pip (can be installed with the `python3-pip` package on Debian)
|
* python3 and pip (can be installed with the `python3-pip` package on Debian)
|
||||||
* the OpenSSL command line tool (can be installed and configured with the
|
* the OpenSSL command line tool (can be installed and configured with the
|
||||||
`libssl-dev` and `pkg-config` packages on Debian)
|
`libssl-dev` and `pkg-config` packages on Debian)
|
||||||
* `nrfutil` (can be installed using `pip3 install nrfutil`) if you want to flash
|
* `nrfutil` (pip package of the same name), if you want to flash
|
||||||
a device with DFU
|
a device with DFU. Read the disclaimer below.
|
||||||
* `uuid-runtime` if you are missing the `uuidgen` command.
|
* `uuid-runtime` if you are missing the `uuidgen` command.
|
||||||
* `llvm` if you want to use the upgradability feature.
|
* `llvm` and `gcc-arm-none-eabi` if you want to use the upgradability feature.
|
||||||
|
|
||||||
The proprietary software to use the default programmer can be found on the
|
The proprietary software to use the default programmer can be found on the
|
||||||
[Segger website](https://www.segger.com/downloads/jlink). Please follow their
|
[Segger website](https://www.segger.com/downloads/jlink). Please follow their
|
||||||
@@ -37,11 +37,17 @@ instructions to appropriate binaries for your system.
|
|||||||
The scripts provided in this project have been tested under Linux and OS X. We
|
The scripts provided in this project have been tested under Linux and OS X. We
|
||||||
haven't tested them on Windows and other platforms.
|
haven't tested them on Windows and other platforms.
|
||||||
|
|
||||||
|
You need `nrfutil` version 6, if you want to flash over DFU.
|
||||||
|
The tool doesn't support Python newer than 3.10. Therefore, we don't officially
|
||||||
|
support DFU for other versions. If you want to try regardless,
|
||||||
|
[Nordic's new tool](https://www.nordicsemi.com/Products/Development-tools/nrf-util)
|
||||||
|
might work for you.
|
||||||
|
|
||||||
### Compiling the firmware
|
### Compiling the firmware
|
||||||
|
|
||||||
If this is your first time installing OpenSK, please skip directly to
|
If this is your first time installing OpenSK, please skip directly to
|
||||||
[Initial setup](#Initial-setup). Else, see
|
[Initial setup](#initial-setup). Else, see
|
||||||
[Updating your setup](#Updating-your-setup) below.
|
[Updating your setup](#updating-your-setup) below.
|
||||||
|
|
||||||
#### Updating your setup
|
#### Updating your setup
|
||||||
|
|
||||||
@@ -56,11 +62,11 @@ following steps:
|
|||||||
./setup.sh
|
./setup.sh
|
||||||
```
|
```
|
||||||
|
|
||||||
* Flash your board according to the
|
* Flash your board according to the [instructions below](#flashing-a-firmware).
|
||||||
[flashing instructions below](#Flashing-a-firmware]. If you come from an
|
|
||||||
OpenSK version before the 2.0 certified one, your credential storage is not
|
If you come from an OpenSK version before the 2.0 certified one, your credential
|
||||||
backwards compatible and you have to reset it. :warning: You will lose
|
storage is not backwards compatible and you have to reset it. :warning: You will
|
||||||
logins to all websites that you registered with OpenSK. To erase your
|
lose logins to all websites that you registered with OpenSK. To erase your
|
||||||
persistent storage, run the deploy script twice: Once with the application
|
persistent storage, run the deploy script twice: Once with the application
|
||||||
parameter `--erase_storage`, and once with `--opensk` as usual.
|
parameter `--erase_storage`, and once with `--opensk` as usual.
|
||||||
|
|
||||||
@@ -134,7 +140,7 @@ From here on, please follow the instructions for your hardware:
|
|||||||
### Advanced installation
|
### Advanced installation
|
||||||
|
|
||||||
We recommend that you flash your development board with JTAG and dongles with
|
We recommend that you flash your development board with JTAG and dongles with
|
||||||
DFU, as described in the [board documentation](#Flashing-a-firmware) linked
|
DFU, as described in the [board documentation](#flashing-a-firmware) linked
|
||||||
above. However, we support other programmers:
|
above. However, we support other programmers:
|
||||||
|
|
||||||
* OpenOCD: `./deploy.py --board=nrf52840_dongle_opensk --opensk
|
* OpenOCD: `./deploy.py --board=nrf52840_dongle_opensk --opensk
|
||||||
|
|||||||
@@ -12,24 +12,32 @@
|
|||||||
// See the License for the specific language governing permissions and
|
// See the License for the specific language governing permissions and
|
||||||
// limitations under the License.
|
// limitations under the License.
|
||||||
|
|
||||||
|
#![no_main]
|
||||||
#![no_std]
|
#![no_std]
|
||||||
|
|
||||||
extern crate lang_items;
|
extern crate lang_items;
|
||||||
|
|
||||||
use libtock_drivers::console::{Console, BUFFER_SIZE};
|
use libtock_console::Console;
|
||||||
|
use libtock_drivers::result::FlexUnwrap;
|
||||||
|
use libtock_runtime::{set_main, stack_size, TockSyscalls};
|
||||||
|
|
||||||
libtock_core::stack_size! {0x800}
|
stack_size! {0x800}
|
||||||
|
set_main! {main}
|
||||||
|
|
||||||
|
type Syscalls = TockSyscalls;
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
// Write messages of length up to the console driver's buffer size.
|
// Write messages of length up to the console driver's buffer size.
|
||||||
let mut buf = [0; BUFFER_SIZE];
|
let mut buf = [0; 1024];
|
||||||
loop {
|
loop {
|
||||||
for i in 1..buf.len() {
|
for i in 1..buf.len() {
|
||||||
for byte in buf.iter_mut().take(i) {
|
for byte in buf.iter_mut().take(i) {
|
||||||
*byte = b'0' + ((i % 10) as u8);
|
*byte = b'0' + ((i % 10) as u8);
|
||||||
}
|
}
|
||||||
buf[i] = b'\n';
|
buf[i] = b'\n';
|
||||||
Console::write_unbuffered(&mut buf[..(i + 1)]);
|
Console::<Syscalls>::write(&buf[..(i + 1)])
|
||||||
|
.map_err(|e| e.into())
|
||||||
|
.flex_unwrap();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -12,182 +12,146 @@
|
|||||||
// See the License for the specific language governing permissions and
|
// See the License for the specific language governing permissions and
|
||||||
// limitations under the License.
|
// limitations under the License.
|
||||||
|
|
||||||
|
#![no_main]
|
||||||
#![no_std]
|
#![no_std]
|
||||||
|
|
||||||
extern crate alloc;
|
extern crate alloc;
|
||||||
extern crate lang_items;
|
extern crate lang_items;
|
||||||
|
|
||||||
|
use alloc::format;
|
||||||
|
use alloc::vec::Vec;
|
||||||
use core::fmt::Write;
|
use core::fmt::Write;
|
||||||
use crypto::sha256::Sha256;
|
use core::hint::black_box;
|
||||||
use crypto::{ecdsa, hybrid};
|
use ctap2::env::tock::{TockEnv, TockRng};
|
||||||
use libtock_drivers::console::Console;
|
use libtock_console::{Console, ConsoleWriter};
|
||||||
use libtock_drivers::result::FlexUnwrap;
|
use libtock_drivers::result::FlexUnwrap;
|
||||||
use libtock_drivers::timer;
|
use libtock_drivers::timer;
|
||||||
use libtock_drivers::timer::{Timer, Timestamp};
|
use libtock_drivers::timer::{Timer, Timestamp};
|
||||||
use rng256::Rng256;
|
use libtock_runtime::{set_main, stack_size, TockSyscalls};
|
||||||
// use ctap2::env::tock::{take_storage, TockStorage};
|
use opensk::api::crypto::aes256::Aes256;
|
||||||
// use persistent_store::Store;
|
use opensk::api::crypto::ecdsa::SecretKey as _;
|
||||||
|
use opensk::api::crypto::sha256::Sha256;
|
||||||
|
use opensk::env::{AesKey, EcdsaSk, Sha};
|
||||||
|
|
||||||
libtock_core::stack_size! {0x11800}
|
stack_size! {0x2000}
|
||||||
|
set_main! {main}
|
||||||
|
|
||||||
/*fn boot_store(mut storage: TockStorage, erase: bool) -> Store<TockStorage> {
|
type Syscalls = TockSyscalls;
|
||||||
use persistent_store::Storage;
|
|
||||||
let num_pages = storage.num_pages();
|
|
||||||
if erase {
|
|
||||||
for page in 0..num_pages {
|
|
||||||
storage.erase_page(page).unwrap();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Store::new(storage).ok().unwrap()
|
|
||||||
}*/
|
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
// Fix to be faster.
|
let mut console = Console::<Syscalls>::writer();
|
||||||
//let storage = take_storage().unwrap();
|
|
||||||
//let mut _store = boot_store(storage, true);
|
|
||||||
|
|
||||||
let mut console = Console::new();
|
|
||||||
let mut rng = rng256::TockRng256 {};
|
|
||||||
// Setup the timer with a dummy callback (we only care about reading the current time, but the
|
// Setup the timer with a dummy callback (we only care about reading the current time, but the
|
||||||
// API forces us to set an alarm callback too).
|
// API forces us to set an alarm callback too).
|
||||||
let mut with_callback = timer::with_callback(|_, _| {});
|
let mut with_callback = timer::with_callback(|_| {});
|
||||||
let timer = with_callback.init().flex_unwrap();
|
let timer = with_callback.init().flex_unwrap();
|
||||||
|
|
||||||
|
let mut rng = TockRng::<Syscalls>::default();
|
||||||
|
|
||||||
writeln!(console, "****************************************").unwrap();
|
writeln!(console, "****************************************").unwrap();
|
||||||
writeln!(
|
writeln!(console, "Clock frequency: {:?} Hz", timer.clock_frequency()).unwrap();
|
||||||
console,
|
|
||||||
"Clock frequency: {} Hz",
|
|
||||||
timer.clock_frequency().hz()
|
|
||||||
)
|
|
||||||
.unwrap();
|
|
||||||
|
|
||||||
custom_bench(
|
// AES
|
||||||
|
bench(&mut console, &timer, "Aes256::new", || {
|
||||||
|
black_box(AesKey::<TockEnv<Syscalls>>::new(&[0; 32]));
|
||||||
|
});
|
||||||
|
let aes_key = AesKey::<TockEnv<Syscalls>>::new(&[0; 32]);
|
||||||
|
|
||||||
|
bench(&mut console, &timer, "Aes256::encrypt_block", || {
|
||||||
|
aes_key.encrypt_block(&mut [0; 16]);
|
||||||
|
});
|
||||||
|
bench(&mut console, &timer, "Aes256::decrypt_block", || {
|
||||||
|
aes_key.decrypt_block(&mut [0; 16]);
|
||||||
|
});
|
||||||
|
|
||||||
|
// CBC
|
||||||
|
let mut blocks = Vec::new();
|
||||||
|
for i in 0..6 {
|
||||||
|
blocks.resize(1 << (i + 4), 0);
|
||||||
|
bench(
|
||||||
&mut console,
|
&mut console,
|
||||||
&timer,
|
&timer,
|
||||||
"ECDSA keygen",
|
&format!("Aes256::encrypt_cbc({} bytes)", blocks.len()),
|
||||||
1000,
|
|
||||||
|| {},
|
|
||||||
|()| {
|
|
||||||
let k = ecdsa::SecKey::gensk(&mut rng);
|
|
||||||
k.genpk();
|
|
||||||
},
|
|
||||||
);
|
|
||||||
|
|
||||||
custom_bench(
|
|
||||||
&mut console,
|
|
||||||
&timer,
|
|
||||||
"ECDSA sign",
|
|
||||||
1000,
|
|
||||||
|| {
|
|| {
|
||||||
let k = ecdsa::SecKey::gensk(&mut rng);
|
aes_key.encrypt_cbc(&[0; 16], &mut blocks);
|
||||||
let mut m = [0; 64];
|
|
||||||
rng.fill_bytes(&mut m);
|
|
||||||
(k, m)
|
|
||||||
},
|
|
||||||
|(k, m)| {
|
|
||||||
k.sign_rfc6979::<Sha256>(&m);
|
|
||||||
},
|
|
||||||
);
|
|
||||||
|
|
||||||
custom_bench(
|
|
||||||
&mut console,
|
|
||||||
&timer,
|
|
||||||
"dilithium::SecKey::gensk_with_pk",
|
|
||||||
1000,
|
|
||||||
|| {},
|
|
||||||
|()| {
|
|
||||||
dilithium::sign::SecKey::gensk_with_pk(&mut rng);
|
|
||||||
},
|
|
||||||
);
|
|
||||||
|
|
||||||
custom_bench(
|
|
||||||
&mut console,
|
|
||||||
&timer,
|
|
||||||
"dilithium::SecKey::sign",
|
|
||||||
1000,
|
|
||||||
|| {
|
|
||||||
let sk = dilithium::sign::SecKey::gensk(&mut rng);
|
|
||||||
let mut m = [0; 64];
|
|
||||||
rng.fill_bytes(&mut m);
|
|
||||||
(sk, m)
|
|
||||||
},
|
|
||||||
|(sk, m)| {
|
|
||||||
sk.sign(&m);
|
|
||||||
},
|
|
||||||
);
|
|
||||||
|
|
||||||
custom_bench(
|
|
||||||
&mut console,
|
|
||||||
&timer,
|
|
||||||
"hybrid::SecKey::gensk_with_pk",
|
|
||||||
1000,
|
|
||||||
|| {},
|
|
||||||
|()| {
|
|
||||||
hybrid::SecKey::gensk_with_pk(&mut rng);
|
|
||||||
},
|
|
||||||
);
|
|
||||||
|
|
||||||
custom_bench(
|
|
||||||
&mut console,
|
|
||||||
&timer,
|
|
||||||
"hybrid::SecKey::sign",
|
|
||||||
1000,
|
|
||||||
|| {
|
|
||||||
let sk = hybrid::SecKey::gensk(&mut rng);
|
|
||||||
let mut m = [0; 64];
|
|
||||||
rng.fill_bytes(&mut m);
|
|
||||||
(sk, m)
|
|
||||||
},
|
|
||||||
|(sk, m)| {
|
|
||||||
sk.sign_rfc6979::<Sha256>(&m).to_asn1_der();
|
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
drop(blocks);
|
||||||
|
|
||||||
fn custom_bench<I, O, F, S>(
|
let mut blocks = Vec::new();
|
||||||
console: &mut Console,
|
for i in 0..6 {
|
||||||
timer: &Timer,
|
blocks.resize(1 << (i + 4), 0);
|
||||||
title: &str,
|
bench(
|
||||||
iter_count: usize,
|
&mut console,
|
||||||
mut setup: S,
|
&timer,
|
||||||
mut f: F,
|
&format!("Aes256::decrypt_cbc({} bytes)", blocks.len()),
|
||||||
) where
|
|| {
|
||||||
S: FnMut() -> I,
|
aes_key.decrypt_cbc(&[0; 16], &mut blocks);
|
||||||
F: FnMut(I) -> O,
|
},
|
||||||
|
);
|
||||||
|
}
|
||||||
|
drop(blocks);
|
||||||
|
|
||||||
|
// SHA-256
|
||||||
|
let mut contents = Vec::new();
|
||||||
|
for i in 0..6 {
|
||||||
|
contents.resize(16 << i, 0);
|
||||||
|
bench(
|
||||||
|
&mut console,
|
||||||
|
&timer,
|
||||||
|
&format!("Sha256::digest({} bytes)", contents.len()),
|
||||||
|
|| {
|
||||||
|
Sha::<TockEnv<Syscalls>>::digest(&contents);
|
||||||
|
},
|
||||||
|
);
|
||||||
|
}
|
||||||
|
drop(contents);
|
||||||
|
|
||||||
|
// ECDSA
|
||||||
|
bench(&mut console, &timer, "Ecdsa::SecretKey::random", || {
|
||||||
|
EcdsaSk::<TockEnv<Syscalls>>::random(&mut rng);
|
||||||
|
});
|
||||||
|
let sk = EcdsaSk::<TockEnv<Syscalls>>::random(&mut rng);
|
||||||
|
bench(&mut console, &timer, "Ecdsa::SecretKey::public_key", || {
|
||||||
|
black_box(sk.public_key());
|
||||||
|
});
|
||||||
|
bench(&mut console, &timer, "Ecdsa::SecretKey::sign", || {
|
||||||
|
sk.sign(&[]);
|
||||||
|
});
|
||||||
|
|
||||||
|
writeln!(console, "****************************************").unwrap();
|
||||||
|
writeln!(console, "All the benchmarks are done.\nHave a nice day!").unwrap();
|
||||||
|
writeln!(console, "****************************************").unwrap();
|
||||||
|
}
|
||||||
|
|
||||||
|
fn bench<F>(console: &mut ConsoleWriter<Syscalls>, timer: &Timer<Syscalls>, title: &str, mut f: F)
|
||||||
|
where
|
||||||
|
F: FnMut(),
|
||||||
{
|
{
|
||||||
writeln!(console, "****************************************").unwrap();
|
writeln!(console, "****************************************").unwrap();
|
||||||
writeln!(console, "Benchmarking: {}", title).unwrap();
|
writeln!(console, "Benchmarking: {}", title).unwrap();
|
||||||
writeln!(console, "----------------------------------------").unwrap();
|
writeln!(console, "----------------------------------------").unwrap();
|
||||||
|
let mut count = 1;
|
||||||
let mut elapsed = 0.0;
|
for _ in 0..30 {
|
||||||
|
let start =
|
||||||
for _ in 1..(iter_count + 1) {
|
Timestamp::<f64>::from_clock_value(timer.get_current_counter_ticks().flex_unwrap());
|
||||||
let inputs = setup();
|
for _ in 0..count {
|
||||||
let start = Timestamp::<f64>::from_clock_value(timer.get_current_clock().flex_unwrap());
|
f();
|
||||||
f(inputs);
|
|
||||||
let end = Timestamp::<f64>::from_clock_value(timer.get_current_clock().flex_unwrap());
|
|
||||||
|
|
||||||
let mut run_duration = (end - start).ms();
|
|
||||||
|
|
||||||
// After 512 seconds, we get a negative difference between the start
|
|
||||||
// time and the end time.
|
|
||||||
if run_duration < 0.0 {
|
|
||||||
run_duration += 512.0 * 1000.0;
|
|
||||||
}
|
}
|
||||||
|
let end =
|
||||||
elapsed += run_duration;
|
Timestamp::<f64>::from_clock_value(timer.get_current_counter_ticks().flex_unwrap());
|
||||||
|
let elapsed = (end - start).ms();
|
||||||
writeln!(console, "{},", run_duration).unwrap();
|
|
||||||
console.flush();
|
|
||||||
}
|
|
||||||
|
|
||||||
writeln!(
|
writeln!(
|
||||||
console,
|
console,
|
||||||
"Total: {} ms elapsed for {} iterations ({} ms/iter)",
|
"{} ms elapsed for {} iterations ({} ms/iter)",
|
||||||
elapsed,
|
elapsed,
|
||||||
iter_count,
|
count,
|
||||||
elapsed / (iter_count as f64)
|
elapsed / (count as f64)
|
||||||
)
|
)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
console.flush();
|
if elapsed > 1000.0 {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
count <<= 1;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -12,18 +12,25 @@
|
|||||||
// See the License for the specific language governing permissions and
|
// See the License for the specific language governing permissions and
|
||||||
// limitations under the License.
|
// limitations under the License.
|
||||||
|
|
||||||
|
#![no_main]
|
||||||
#![no_std]
|
#![no_std]
|
||||||
|
|
||||||
extern crate lang_items;
|
extern crate lang_items;
|
||||||
|
|
||||||
use core::fmt::Write;
|
use core::fmt::Write;
|
||||||
use ctap2::env::tock::take_storage;
|
use ctap2::env::tock::take_storage;
|
||||||
use libtock_drivers::console::Console;
|
use libtock_console::Console;
|
||||||
use libtock_drivers::led;
|
|
||||||
use libtock_drivers::result::FlexUnwrap;
|
use libtock_drivers::result::FlexUnwrap;
|
||||||
|
use libtock_leds::Leds;
|
||||||
|
use libtock_platform as platform;
|
||||||
|
use libtock_runtime::{set_main, stack_size, TockSyscalls};
|
||||||
use persistent_store::{Storage, StorageIndex};
|
use persistent_store::{Storage, StorageIndex};
|
||||||
|
use platform::DefaultConfig;
|
||||||
|
|
||||||
libtock_core::stack_size! {0x800}
|
stack_size! {0x800}
|
||||||
|
set_main! {main}
|
||||||
|
|
||||||
|
type Syscalls = TockSyscalls;
|
||||||
|
|
||||||
fn is_page_erased(storage: &dyn Storage, page: usize) -> bool {
|
fn is_page_erased(storage: &dyn Storage, page: usize) -> bool {
|
||||||
let index = StorageIndex { page, byte: 0 };
|
let index = StorageIndex { page, byte: 0 };
|
||||||
@@ -36,20 +43,21 @@ fn is_page_erased(storage: &dyn Storage, page: usize) -> bool {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
led::get(1).flex_unwrap().on().flex_unwrap(); // red on dongle
|
Leds::<Syscalls>::on(1).map_err(|e| e.into()).flex_unwrap(); // red on dongle
|
||||||
let mut storage = take_storage().unwrap();
|
let mut storage = take_storage::<Syscalls, DefaultConfig>().unwrap();
|
||||||
let num_pages = storage.num_pages();
|
let num_pages = storage.num_pages();
|
||||||
writeln!(Console::new(), "Erase {} pages of storage:", num_pages).unwrap();
|
let mut console = Console::<Syscalls>::writer();
|
||||||
|
writeln!(console, "Erase {} pages of storage:", num_pages).unwrap();
|
||||||
for page in 0..num_pages {
|
for page in 0..num_pages {
|
||||||
write!(Console::new(), "- Page {} ", page).unwrap();
|
write!(console, "- Page {} ", page).unwrap();
|
||||||
if is_page_erased(&storage, page) {
|
if is_page_erased(&storage, page) {
|
||||||
writeln!(Console::new(), "skipped (was already erased).").unwrap();
|
writeln!(console, "skipped (was already erased).").unwrap();
|
||||||
} else {
|
} else {
|
||||||
storage.erase_page(page).unwrap();
|
storage.erase_page(page).unwrap();
|
||||||
writeln!(Console::new(), "erased.").unwrap();
|
writeln!(console, "erased.").unwrap();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
writeln!(Console::new(), "Done.").unwrap();
|
writeln!(console, "Done.").unwrap();
|
||||||
led::get(1).flex_unwrap().off().flex_unwrap();
|
Leds::<Syscalls>::on(1).map_err(|e| e.into()).flex_unwrap();
|
||||||
led::get(0).flex_unwrap().on().flex_unwrap(); // green on dongle
|
Leds::<Syscalls>::off(0).map_err(|e| e.into()).flex_unwrap(); // green on dongle
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,184 +0,0 @@
|
|||||||
// Copyright 2022 Google LLC
|
|
||||||
//
|
|
||||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
// you may not use this file except in compliance with the License.
|
|
||||||
// You may obtain a copy of the License at
|
|
||||||
//
|
|
||||||
// http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
//
|
|
||||||
// Unless required by applicable law or agreed to in writing, software
|
|
||||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
// See the License for the specific language governing permissions and
|
|
||||||
// limitations under the License.
|
|
||||||
|
|
||||||
#![no_std]
|
|
||||||
#![feature(asm)]
|
|
||||||
#![feature(llvm_asm)]
|
|
||||||
#![allow(dead_code)]
|
|
||||||
|
|
||||||
extern crate alloc;
|
|
||||||
extern crate lang_items;
|
|
||||||
|
|
||||||
use core::fmt::Write;
|
|
||||||
use core::ptr;
|
|
||||||
use crypto::sha256::Sha256;
|
|
||||||
use crypto::{ecdsa, hybrid, sha256};
|
|
||||||
use libtock_drivers::console::Console;
|
|
||||||
|
|
||||||
libtock_core::stack_size! {0x11800}
|
|
||||||
|
|
||||||
#[inline(never)]
|
|
||||||
fn read_stack_pointer() -> u32 {
|
|
||||||
let x = 1u32;
|
|
||||||
let address = &x as *const u32;
|
|
||||||
address as u32
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline(never)]
|
|
||||||
fn print_stack_pointer(console: &mut Console) {
|
|
||||||
let x = 1u32;
|
|
||||||
writeln!(console, "Stack pointer: {:?}", &x as *const u32).unwrap();
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Writes a byte pattern to a memory range.
|
|
||||||
///
|
|
||||||
/// Since the stack grows to lower addresses, end < start.
|
|
||||||
/// Addresses after start must be unused, i.e. start must be at least the current stack pointer.
|
|
||||||
/// Addresses until end should be within the stack area.
|
|
||||||
unsafe fn paint_memory(start: u32, end: u32) {
|
|
||||||
for address in (end..start).step_by(4) {
|
|
||||||
let p = address as *const u32;
|
|
||||||
ptr::write(p as *mut u32, 0xCDCDCDCD);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Find the lowest address that does not have the 0xCD pattern.
|
|
||||||
unsafe fn find_border(start: u32, end: u32) -> u32 {
|
|
||||||
for address in (end..start).step_by(4) {
|
|
||||||
let p = address as *const u32;
|
|
||||||
if ptr::read(p) != 0xCDCDCDCD {
|
|
||||||
return address;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
start
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline(never)]
|
|
||||||
pub fn black_box<T>(dummy: T) -> T {
|
|
||||||
unsafe { llvm_asm!("" : : "r"(&dummy)) }
|
|
||||||
dummy
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline(never)]
|
|
||||||
fn keygen_ecdsa(rng: &mut rng256::TockRng256) {
|
|
||||||
let sk = ecdsa::SecKey::gensk(rng);
|
|
||||||
black_box(sk);
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline(never)]
|
|
||||||
fn keygen_dilithium(rng: &mut rng256::TockRng256) {
|
|
||||||
let sk = dilithium::sign::SecKey::gensk(rng);
|
|
||||||
black_box(sk);
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline(never)]
|
|
||||||
fn keygen_hybrid(rng: &mut rng256::TockRng256) {
|
|
||||||
let sk = hybrid::SecKey::gensk_with_pk(rng);
|
|
||||||
black_box(sk);
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline(never)]
|
|
||||||
fn sign_ecdsa(rng: &mut rng256::TockRng256, sk: &ecdsa::SecKey) {
|
|
||||||
let sig = sk.sign_rng::<sha256::Sha256, _>(&[], rng);
|
|
||||||
black_box(sig);
|
|
||||||
}
|
|
||||||
|
|
||||||
fn sign_dilithium(sk: &dilithium::sign::SecKey) {
|
|
||||||
let sig = sk.sign(&[]);
|
|
||||||
black_box(sig);
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline(never)]
|
|
||||||
fn sign_hybrid(sk: &hybrid::SecKey) {
|
|
||||||
let sig = sk.sign_rfc6979::<Sha256>(&[]);
|
|
||||||
black_box(sig);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Measure the stack usage of the method itself, plus a u32.
|
|
||||||
#[inline(never)]
|
|
||||||
fn dummy_test() {
|
|
||||||
let x = 1u32;
|
|
||||||
black_box(x);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Tests whether input parameters are correctly ignored in the measurement.
|
|
||||||
#[inline(never)]
|
|
||||||
fn param_test(big_param: &mut [u8; 0x1000]) {
|
|
||||||
let x = 0x01;
|
|
||||||
big_param[0] = x;
|
|
||||||
black_box(x);
|
|
||||||
}
|
|
||||||
|
|
||||||
fn write_result(console: &mut Console, text: &str, size: u32) {
|
|
||||||
writeln!(console, "{} size: 0x{:08X}", text, size).unwrap();
|
|
||||||
}
|
|
||||||
|
|
||||||
fn main() {
|
|
||||||
let mut console = Console::new();
|
|
||||||
|
|
||||||
let x = 1u32;
|
|
||||||
let sp = &x as *const u32;
|
|
||||||
// Should be safe to write from here.
|
|
||||||
let start = sp as u32 - 0x100u32;
|
|
||||||
writeln!(console, "Search start address: 0x{:08X}", start).unwrap();
|
|
||||||
print_stack_pointer(&mut console);
|
|
||||||
|
|
||||||
let mut rng = rng256::TockRng256 {};
|
|
||||||
|
|
||||||
unsafe { paint_memory(start, 0x20020000) };
|
|
||||||
keygen_ecdsa(&mut rng);
|
|
||||||
let min_address1 = unsafe { find_border(start, 0x20020000) };
|
|
||||||
|
|
||||||
unsafe { paint_memory(start, 0x20020000) };
|
|
||||||
keygen_dilithium(&mut rng);
|
|
||||||
let min_address2 = unsafe { find_border(start, 0x20020000) };
|
|
||||||
|
|
||||||
unsafe { paint_memory(start, 0x20020000) };
|
|
||||||
keygen_hybrid(&mut rng);
|
|
||||||
let min_address3 = unsafe { find_border(start, 0x20020000) };
|
|
||||||
|
|
||||||
let sk = ecdsa::SecKey::gensk(&mut rng);
|
|
||||||
unsafe { paint_memory(start, 0x20020000) };
|
|
||||||
sign_ecdsa(&mut rng, &sk);
|
|
||||||
let min_address4 = unsafe { find_border(start, 0x20020000) };
|
|
||||||
|
|
||||||
let sk = dilithium::sign::SecKey::gensk(&mut rng);
|
|
||||||
unsafe { paint_memory(start, 0x20020000) };
|
|
||||||
sign_dilithium(&sk);
|
|
||||||
let min_address5 = unsafe { find_border(start, 0x20020000) };
|
|
||||||
|
|
||||||
let sk = hybrid::SecKey::gensk(&mut rng);
|
|
||||||
unsafe { paint_memory(start, 0x20020000) };
|
|
||||||
sign_hybrid(&sk);
|
|
||||||
let min_address6 = unsafe { find_border(start, 0x20020000) };
|
|
||||||
|
|
||||||
let mut param = [0; 0x1000];
|
|
||||||
unsafe { paint_memory(start, 0x20020000) };
|
|
||||||
param_test(&mut param);
|
|
||||||
let min_address7 = unsafe { find_border(start, 0x20020000) };
|
|
||||||
|
|
||||||
unsafe { paint_memory(start, 0x20020000) };
|
|
||||||
dummy_test();
|
|
||||||
let min_address8 = unsafe { find_border(start, 0x20020000) };
|
|
||||||
|
|
||||||
let main_end = read_stack_pointer();
|
|
||||||
write_result(&mut console, " keygen_ecdsa", main_end - min_address1);
|
|
||||||
write_result(&mut console, "keygen_dilithium", main_end - min_address2);
|
|
||||||
write_result(&mut console, " keygen_hybrid", main_end - min_address3);
|
|
||||||
write_result(&mut console, " sign_ecdsa", main_end - min_address4);
|
|
||||||
write_result(&mut console, " sign_dilithium", main_end - min_address5);
|
|
||||||
write_result(&mut console, " sign_hybrid", main_end - min_address6);
|
|
||||||
write_result(&mut console, " test dummy", main_end - min_address7);
|
|
||||||
write_result(&mut console, " test input", main_end - min_address8);
|
|
||||||
}
|
|
||||||
@@ -1,3 +1,4 @@
|
|||||||
|
#![no_main]
|
||||||
#![no_std]
|
#![no_std]
|
||||||
|
|
||||||
extern crate alloc;
|
extern crate alloc;
|
||||||
@@ -5,27 +6,32 @@ extern crate lang_items;
|
|||||||
extern crate libtock_drivers;
|
extern crate libtock_drivers;
|
||||||
|
|
||||||
use core::fmt::Write;
|
use core::fmt::Write;
|
||||||
use libtock_drivers::console::Console;
|
use libtock_console::{Console, ConsoleWriter};
|
||||||
|
use libtock_runtime::{set_main, stack_size, TockSyscalls};
|
||||||
|
|
||||||
libtock_core::stack_size! {0x4000}
|
stack_size! {0x4000}
|
||||||
|
set_main! {main}
|
||||||
|
|
||||||
|
type Syscalls = TockSyscalls;
|
||||||
|
|
||||||
#[cfg(not(feature = "with_nfc"))]
|
#[cfg(not(feature = "with_nfc"))]
|
||||||
mod example {
|
mod example {
|
||||||
use super::{Console, Write};
|
use super::{ConsoleWriter, Syscalls, Write};
|
||||||
|
|
||||||
pub fn nfc(console: &mut Console) {
|
pub fn nfc(console: &mut ConsoleWriter<Syscalls>) {
|
||||||
writeln!(console, "NFC feature flag is missing!").unwrap();
|
writeln!(console, "NFC feature flag is missing!").unwrap();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "with_nfc")]
|
#[cfg(feature = "with_nfc")]
|
||||||
mod example {
|
mod example {
|
||||||
use super::{Console, Write};
|
use super::{Console, ConsoleWriter, Write};
|
||||||
use libtock_core::result::CommandError;
|
use crate::Syscalls;
|
||||||
use libtock_drivers::nfc::{NfcTag, RecvOp};
|
use libtock_drivers::nfc::{NfcTag, RecvOp};
|
||||||
use libtock_drivers::result::{FlexUnwrap, TockError};
|
use libtock_drivers::result::{FlexUnwrap, TockError};
|
||||||
use libtock_drivers::timer;
|
use libtock_drivers::timer;
|
||||||
use libtock_drivers::timer::{Timer, Timestamp};
|
use libtock_drivers::timer::{Timer, Timestamp};
|
||||||
|
use libtock_platform::{DefaultConfig, ErrorCode};
|
||||||
|
|
||||||
#[derive(Copy, Clone, Debug, PartialEq)]
|
#[derive(Copy, Clone, Debug, PartialEq)]
|
||||||
#[allow(clippy::upper_case_acronyms)]
|
#[allow(clippy::upper_case_acronyms)]
|
||||||
@@ -48,16 +54,15 @@ mod example {
|
|||||||
ENOSUPPORT,
|
ENOSUPPORT,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<isize> for ReturnCode {
|
impl From<ErrorCode> for ReturnCode {
|
||||||
fn from(original: isize) -> ReturnCode {
|
fn from(original: ErrorCode) -> ReturnCode {
|
||||||
match original {
|
match original {
|
||||||
0 => ReturnCode::SUCCESS,
|
ErrorCode::Fail => ReturnCode::FAIL,
|
||||||
-1 => ReturnCode::FAIL,
|
ErrorCode::Busy => ReturnCode::EBUSY,
|
||||||
-2 => ReturnCode::EBUSY,
|
ErrorCode::Off => ReturnCode::EOFF,
|
||||||
-4 => ReturnCode::EOFF,
|
ErrorCode::Invalid => ReturnCode::EINVAL,
|
||||||
-6 => ReturnCode::EINVAL,
|
ErrorCode::Cancel => ReturnCode::ECANCEL,
|
||||||
-8 => ReturnCode::ECANCEL,
|
ErrorCode::NoMem => ReturnCode::ENOMEM,
|
||||||
-9 => ReturnCode::ENOMEM,
|
|
||||||
_ => ReturnCode::ENOSUPPORT,
|
_ => ReturnCode::ENOSUPPORT,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -66,34 +71,32 @@ mod example {
|
|||||||
/// Helper function to write on console the received packet.
|
/// Helper function to write on console the received packet.
|
||||||
fn print_rx_buffer(buf: &mut [u8]) {
|
fn print_rx_buffer(buf: &mut [u8]) {
|
||||||
if let Some((last, bytes)) = buf.split_last() {
|
if let Some((last, bytes)) = buf.split_last() {
|
||||||
let mut console = Console::new();
|
let mut console = Console::<Syscalls>::writer();
|
||||||
write!(console, "RX:").unwrap();
|
write!(console, "RX:").unwrap();
|
||||||
for byte in bytes {
|
for byte in bytes {
|
||||||
write!(console, " {:02x?}", byte).unwrap();
|
write!(console, " {:02x?}", byte).unwrap();
|
||||||
}
|
}
|
||||||
writeln!(console, " {:02x?}", last).unwrap();
|
writeln!(console, " {:02x?}", last).unwrap();
|
||||||
console.flush();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Function to identify the time elapsed for a transmission request.
|
/// Function to identify the time elapsed for a transmission request.
|
||||||
fn bench_transmit(
|
fn bench_transmit(
|
||||||
console: &mut Console,
|
console: &mut ConsoleWriter<Syscalls>,
|
||||||
timer: &Timer,
|
timer: &Timer<Syscalls>,
|
||||||
title: &str,
|
title: &str,
|
||||||
mut buf: &mut [u8],
|
buf: &mut [u8],
|
||||||
) -> ReturnCode {
|
) -> ReturnCode {
|
||||||
let amount = buf.len();
|
let amount = buf.len();
|
||||||
let start = Timestamp::<f64>::from_clock_value(timer.get_current_clock().flex_unwrap());
|
let start =
|
||||||
match NfcTag::transmit(&mut buf, amount) {
|
Timestamp::<f64>::from_clock_value(timer.get_current_counter_ticks().flex_unwrap());
|
||||||
|
match NfcTag::<Syscalls, DefaultConfig>::transmit(buf, amount as u32) {
|
||||||
Ok(_) => (),
|
Ok(_) => (),
|
||||||
Err(TockError::Command(CommandError {
|
Err(TockError::Command(ErrorCode::Cancel)) => return ReturnCode::ECANCEL,
|
||||||
return_code: -8, /* ECANCEL: No Field*/
|
Err(_) => writeln!(console, " -- tx error!").unwrap(),
|
||||||
..
|
|
||||||
})) => return ReturnCode::ECANCEL,
|
|
||||||
Err(_) => writeln!(Console::new(), " -- tx error!").unwrap(),
|
|
||||||
}
|
}
|
||||||
let end = Timestamp::<f64>::from_clock_value(timer.get_current_clock().flex_unwrap());
|
let end =
|
||||||
|
Timestamp::<f64>::from_clock_value(timer.get_current_counter_ticks().flex_unwrap());
|
||||||
let elapsed = (end - start).ms();
|
let elapsed = (end - start).ms();
|
||||||
writeln!(
|
writeln!(
|
||||||
console,
|
console,
|
||||||
@@ -104,21 +107,21 @@ mod example {
|
|||||||
(amount as f64) / elapsed * 8.
|
(amount as f64) / elapsed * 8.
|
||||||
)
|
)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
console.flush();
|
|
||||||
ReturnCode::SUCCESS
|
ReturnCode::SUCCESS
|
||||||
}
|
}
|
||||||
|
|
||||||
fn receive_packet(console: &mut Console, mut buf: &mut [u8; 256]) -> ReturnCode {
|
fn receive_packet(console: &mut ConsoleWriter<Syscalls>, buf: &mut [u8; 256]) -> ReturnCode {
|
||||||
match NfcTag::receive(&mut buf) {
|
match NfcTag::<Syscalls, DefaultConfig>::receive(buf) {
|
||||||
Ok(RecvOp {
|
Ok(RecvOp {
|
||||||
recv_amount: amount,
|
recv_amount: amount,
|
||||||
..
|
..
|
||||||
}) => {
|
}) => {
|
||||||
if amount <= buf.len() {
|
if amount <= buf.len() as u32 {
|
||||||
print_rx_buffer(&mut buf[..amount]);
|
print_rx_buffer(&mut buf[..amount as usize]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Err(TockError::Command(CommandError { return_code, .. })) => return return_code.into(),
|
Err(TockError::Command(code)) => return code.into(),
|
||||||
Err(_) => {
|
Err(_) => {
|
||||||
writeln!(console, " -- RX Err").unwrap();
|
writeln!(console, " -- RX Err").unwrap();
|
||||||
return ReturnCode::ECANCEL;
|
return ReturnCode::ECANCEL;
|
||||||
@@ -127,54 +130,58 @@ mod example {
|
|||||||
ReturnCode::SUCCESS
|
ReturnCode::SUCCESS
|
||||||
}
|
}
|
||||||
|
|
||||||
fn transmit_reply(mut console: &mut Console, timer: &Timer, buf: &[u8]) -> ReturnCode {
|
fn transmit_reply(
|
||||||
|
console: &mut ConsoleWriter<Syscalls>,
|
||||||
|
timer: &Timer<Syscalls>,
|
||||||
|
buf: &[u8],
|
||||||
|
) -> ReturnCode {
|
||||||
let mut return_code = ReturnCode::SUCCESS;
|
let mut return_code = ReturnCode::SUCCESS;
|
||||||
match buf[0] {
|
match buf[0] {
|
||||||
0xe0 /* RATS */=> {
|
0xe0 /* RATS */=> {
|
||||||
let mut answer_to_select = [0x05, 0x78, 0x80, 0xB1, 0x00];
|
let mut answer_to_select = [0x05, 0x78, 0x80, 0xB1, 0x00];
|
||||||
return_code = bench_transmit(&mut console, timer, "TX: ATS", &mut answer_to_select);
|
return_code = bench_transmit(console, timer, "TX: ATS", &mut answer_to_select);
|
||||||
}
|
}
|
||||||
0xc2 /* DESELECT */ => {
|
0xc2 /* DESELECT */ => {
|
||||||
// Ignore the request
|
// Ignore the request
|
||||||
let mut command_error = [0x6A, 0x81];
|
let mut command_error = [0x6A, 0x81];
|
||||||
return_code = bench_transmit(&mut console, timer, "TX: DESELECT", &mut command_error);
|
return_code = bench_transmit(console, timer, "TX: DESELECT", &mut command_error);
|
||||||
}
|
}
|
||||||
0x02 | 0x03 /* APDU Prefix */ => match buf[2] {
|
0x02 | 0x03 /* APDU Prefix */ => match buf[2] {
|
||||||
// If the received packet is applet selection command (FIDO 2)
|
// If the received packet is applet selection command (FIDO 2)
|
||||||
0xa4 /* SELECT */ => if buf[3] == 0x04 && buf[5] == 0x08 && buf[6] == 0xa0 {
|
0xa4 /* SELECT */ => if buf[3] == 0x04 && buf[5] == 0x08 && buf[6] == 0xa0 {
|
||||||
// Vesion: "FIDO_2_0"
|
// Vesion: "FIDO_2_0"
|
||||||
let mut reply = [buf[0], 0x46, 0x49, 0x44, 0x4f, 0x5f, 0x32, 0x5f, 0x30, 0x90, 0x00,];
|
let mut reply = [buf[0], 0x46, 0x49, 0x44, 0x4f, 0x5f, 0x32, 0x5f, 0x30, 0x90, 0x00,];
|
||||||
return_code = bench_transmit(&mut console, timer, "TX: Version Str", &mut reply);
|
return_code = bench_transmit(console, timer, "TX: Version Str", &mut reply);
|
||||||
} else if (buf[6] == 0xd2 && buf[7] == 0x76) || (buf[6] == 0xe1 && (buf[7] == 0x03 || buf[7] == 0x04)){
|
} else if (buf[6] == 0xd2 && buf[7] == 0x76) || (buf[6] == 0xe1 && (buf[7] == 0x03 || buf[7] == 0x04)){
|
||||||
let mut reply = [buf[0], 0x90, 0x00];
|
let mut reply = [buf[0], 0x90, 0x00];
|
||||||
return_code = bench_transmit(&mut console, timer, "TX: 0x9000", &mut reply);
|
return_code = bench_transmit(console, timer, "TX: 0x9000", &mut reply);
|
||||||
} else /* Unknown file */ {
|
} else /* Unknown file */ {
|
||||||
let mut reply = [buf[0], 0x6a, 0x82];
|
let mut reply = [buf[0], 0x6a, 0x82];
|
||||||
return_code = bench_transmit(&mut console, timer, "TX: 0x6A82", &mut reply);
|
return_code = bench_transmit(console, timer, "TX: 0x6A82", &mut reply);
|
||||||
}
|
}
|
||||||
0xb0 /* READ */ => match buf[5] {
|
0xb0 /* READ */ => match buf[5] {
|
||||||
0x02 => {
|
0x02 => {
|
||||||
let mut reply = [buf[0], 0x12, 0x90, 0x00,];
|
let mut reply = [buf[0], 0x12, 0x90, 0x00,];
|
||||||
return_code = bench_transmit(&mut console, timer, "TX: File Size", &mut reply);
|
return_code = bench_transmit(console, timer, "TX: File Size", &mut reply);
|
||||||
}
|
}
|
||||||
0x12 => {
|
0x12 => {
|
||||||
let mut reply = [buf[0], 0xd1, 0x01, 0x0e, 0x55, 0x77, 0x77, 0x77, 0x2e, 0x6f, 0x70, 0x65,
|
let mut reply = [buf[0], 0xd1, 0x01, 0x0e, 0x55, 0x77, 0x77, 0x77, 0x2e, 0x6f, 0x70, 0x65,
|
||||||
0x6e, 0x73, 0x6b, 0x2e, 0x64, 0x65, 0x76, 0x90, 0x00,];
|
0x6e, 0x73, 0x6b, 0x2e, 0x64, 0x65, 0x76, 0x90, 0x00,];
|
||||||
return_code = bench_transmit(&mut console, timer, "TX: NDEF", &mut reply);
|
return_code = bench_transmit(console, timer, "TX: NDEF", &mut reply);
|
||||||
}
|
}
|
||||||
0x0f => {
|
0x0f => {
|
||||||
let mut reply = [buf[0], 0x00, 0x0f, 0x20, 0x00, 0x7f, 0x00, 0x7f, 0x04, 0x06, 0xe1, 0x04,
|
let mut reply = [buf[0], 0x00, 0x0f, 0x20, 0x00, 0x7f, 0x00, 0x7f, 0x04, 0x06, 0xe1, 0x04,
|
||||||
0x00, 0x7f, 0x00, 0x00, 0x90, 0x00,];
|
0x00, 0x7f, 0x00, 0x00, 0x90, 0x00,];
|
||||||
return_code = bench_transmit(&mut console, timer, "TX: CC", &mut reply);
|
return_code = bench_transmit(console, timer, "TX: CC", &mut reply);
|
||||||
}
|
}
|
||||||
_ => {
|
_ => {
|
||||||
let mut reply = [buf[0], 0x90, 0x00];
|
let mut reply = [buf[0], 0x90, 0x00];
|
||||||
return_code = bench_transmit(&mut console, timer, "TX: 0x9000", &mut reply);
|
return_code = bench_transmit(console, timer, "TX: 0x9000", &mut reply);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
_ => {
|
_ => {
|
||||||
let mut reply = [buf[0], 0x90, 0x00];
|
let mut reply = [buf[0], 0x90, 0x00];
|
||||||
return_code = bench_transmit(&mut console, timer, "TX: 0x9000", &mut reply);
|
return_code = bench_transmit(console, timer, "TX: 0x9000", &mut reply);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
0x26 | 0x52 | 0x50 /* REQA | WUPA | Halt */ => {
|
0x26 | 0x52 | 0x50 /* REQA | WUPA | Halt */ => {
|
||||||
@@ -185,31 +192,27 @@ mod example {
|
|||||||
return_code
|
return_code
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn nfc(mut console: &mut Console) {
|
pub fn nfc(console: &mut ConsoleWriter<Syscalls>) {
|
||||||
// Setup the timer with a dummy callback (we only care about reading the current time, but the
|
// Setup the timer with a dummy callback (we only care about reading the current time, but the
|
||||||
// API forces us to set an alarm callback too).
|
// API forces us to set an alarm callback too).
|
||||||
let mut with_callback = timer::with_callback(|_, _| {});
|
let mut with_callback = timer::with_callback(|_| {});
|
||||||
|
|
||||||
let timer = with_callback.init().flex_unwrap();
|
let timer = with_callback.init().flex_unwrap();
|
||||||
|
|
||||||
writeln!(
|
writeln!(console, "Clock frequency: {:?} Hz", timer.clock_frequency()).unwrap();
|
||||||
console,
|
|
||||||
"Clock frequency: {} Hz",
|
|
||||||
timer.clock_frequency().hz()
|
|
||||||
)
|
|
||||||
.unwrap();
|
|
||||||
|
|
||||||
let mut state_change_counter = 0;
|
let mut state_change_counter = 0;
|
||||||
loop {
|
loop {
|
||||||
let mut rx_buf = [0; 256];
|
let mut rx_buf = [0; 256];
|
||||||
match receive_packet(&mut console, &mut rx_buf) {
|
match receive_packet(console, &mut rx_buf) {
|
||||||
ReturnCode::EOFF => {
|
ReturnCode::EOFF => {
|
||||||
// Not configured
|
// Not configured
|
||||||
while !NfcTag::enable_emulation() {}
|
while !NfcTag::<Syscalls, DefaultConfig>::enable_emulation() {}
|
||||||
// Configure Type 4 tag
|
// Configure Type 4 tag
|
||||||
while !NfcTag::configure(4) {}
|
while !NfcTag::<Syscalls, DefaultConfig>::configure(4) {}
|
||||||
}
|
}
|
||||||
ReturnCode::ECANCEL /* field lost */ => {
|
ReturnCode::ECANCEL /* field lost */ => {
|
||||||
NfcTag::disable_emulation();
|
NfcTag::<Syscalls, DefaultConfig>::disable_emulation();
|
||||||
}
|
}
|
||||||
ReturnCode::EBUSY /* awaiting select*/ => (),
|
ReturnCode::EBUSY /* awaiting select*/ => (),
|
||||||
ReturnCode::ENOMEM => {
|
ReturnCode::ENOMEM => {
|
||||||
@@ -220,9 +223,9 @@ mod example {
|
|||||||
ReturnCode::ENOSUPPORT => (),
|
ReturnCode::ENOSUPPORT => (),
|
||||||
ReturnCode::SUCCESS => {
|
ReturnCode::SUCCESS => {
|
||||||
// If the reader restarts the communication then disable the tag.
|
// If the reader restarts the communication then disable the tag.
|
||||||
match transmit_reply(&mut console, &timer, &rx_buf) {
|
match transmit_reply(console, &timer, &rx_buf) {
|
||||||
ReturnCode::ECANCEL | ReturnCode::EOFF => {
|
ReturnCode::ECANCEL | ReturnCode::EOFF => {
|
||||||
if NfcTag::disable_emulation() {
|
if NfcTag::<Syscalls, DefaultConfig>::disable_emulation() {
|
||||||
writeln!(console, " -- TAG DISABLED").unwrap();
|
writeln!(console, " -- TAG DISABLED").unwrap();
|
||||||
}
|
}
|
||||||
state_change_counter += 1;
|
state_change_counter += 1;
|
||||||
@@ -239,7 +242,7 @@ mod example {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
let mut console = Console::new();
|
let mut console = Console::<Syscalls>::writer();
|
||||||
writeln!(console, "****************************************").unwrap();
|
writeln!(console, "****************************************").unwrap();
|
||||||
writeln!(console, "nfct_test application is installed").unwrap();
|
writeln!(console, "nfct_test application is installed").unwrap();
|
||||||
example::nfc(&mut console);
|
example::nfc(&mut console);
|
||||||
|
|||||||
@@ -12,24 +12,30 @@
|
|||||||
// See the License for the specific language governing permissions and
|
// See the License for the specific language governing permissions and
|
||||||
// limitations under the License.
|
// limitations under the License.
|
||||||
|
|
||||||
|
#![no_main]
|
||||||
#![no_std]
|
#![no_std]
|
||||||
|
|
||||||
extern crate alloc;
|
extern crate alloc;
|
||||||
extern crate lang_items;
|
extern crate lang_items;
|
||||||
|
|
||||||
libtock_core::stack_size! {0x800}
|
|
||||||
|
|
||||||
use alloc::vec::Vec;
|
use alloc::vec::Vec;
|
||||||
use core::fmt::Write;
|
use core::fmt::Write;
|
||||||
use libtock_drivers::console::Console;
|
use libtock_console::Console;
|
||||||
|
use libtock_runtime::{set_main, stack_size, TockSyscalls};
|
||||||
|
|
||||||
|
stack_size! {0x800}
|
||||||
|
set_main! {main}
|
||||||
|
|
||||||
|
type Syscalls = TockSyscalls;
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
writeln!(Console::new(), "****************************************").unwrap();
|
let mut console = Console::<Syscalls>::writer();
|
||||||
|
writeln!(console, "****************************************").unwrap();
|
||||||
for i in 0.. {
|
for i in 0.. {
|
||||||
writeln!(Console::new(), "Allocating {} bytes...", 1 << i).unwrap();
|
writeln!(console, "Allocating {} bytes...", 1 << i).unwrap();
|
||||||
let x: Vec<u8> = Vec::with_capacity(1 << i);
|
let x: Vec<u8> = Vec::with_capacity(1 << i);
|
||||||
writeln!(Console::new(), "Allocated!").unwrap();
|
writeln!(console, "Allocated!").unwrap();
|
||||||
drop(x);
|
drop(x);
|
||||||
writeln!(Console::new(), "Dropped!").unwrap();
|
writeln!(console, "Dropped!").unwrap();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -12,11 +12,15 @@
|
|||||||
// See the License for the specific language governing permissions and
|
// See the License for the specific language governing permissions and
|
||||||
// limitations under the License.
|
// limitations under the License.
|
||||||
|
|
||||||
|
#![no_main]
|
||||||
#![no_std]
|
#![no_std]
|
||||||
|
|
||||||
extern crate lang_items;
|
extern crate lang_items;
|
||||||
|
|
||||||
libtock_core::stack_size! {0x800}
|
use libtock_runtime::{set_main, stack_size};
|
||||||
|
|
||||||
|
stack_size! {0x800}
|
||||||
|
set_main! {main}
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
panic!("Bye world!")
|
panic!("Bye world!")
|
||||||
|
|||||||
@@ -12,6 +12,7 @@
|
|||||||
// See the License for the specific language governing permissions and
|
// See the License for the specific language governing permissions and
|
||||||
// limitations under the License.
|
// limitations under the License.
|
||||||
|
|
||||||
|
#![no_main]
|
||||||
#![no_std]
|
#![no_std]
|
||||||
|
|
||||||
extern crate alloc;
|
extern crate alloc;
|
||||||
@@ -21,26 +22,34 @@ use alloc::string::{String, ToString};
|
|||||||
use alloc::vec::Vec;
|
use alloc::vec::Vec;
|
||||||
use alloc::{format, vec};
|
use alloc::{format, vec};
|
||||||
use core::fmt::Write;
|
use core::fmt::Write;
|
||||||
use ctap2::env::tock::{take_storage, TockStorage};
|
use ctap2::env::tock::{take_storage, Storage};
|
||||||
use libtock_drivers::console::Console;
|
use libtock_console::Console;
|
||||||
|
use libtock_drivers::result::FlexUnwrap;
|
||||||
use libtock_drivers::timer::{self, Duration, Timer, Timestamp};
|
use libtock_drivers::timer::{self, Duration, Timer, Timestamp};
|
||||||
use persistent_store::Store;
|
use libtock_platform::DefaultConfig;
|
||||||
|
use libtock_runtime::{set_main, stack_size, TockSyscalls};
|
||||||
|
use persistent_store::{Storage as _, Store};
|
||||||
|
|
||||||
libtock_core::stack_size! {0x2000}
|
stack_size! {0x800}
|
||||||
|
set_main! {main}
|
||||||
|
|
||||||
fn timestamp(timer: &Timer) -> Timestamp<f64> {
|
type Syscalls = TockSyscalls;
|
||||||
Timestamp::<f64>::from_clock_value(timer.get_current_clock().ok().unwrap())
|
|
||||||
|
fn timestamp(timer: &Timer<Syscalls>) -> Timestamp<f64> {
|
||||||
|
Timestamp::<f64>::from_clock_value(timer.get_current_counter_ticks().ok().unwrap())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn measure<T>(timer: &Timer, operation: impl FnOnce() -> T) -> (T, Duration<f64>) {
|
fn measure<T>(timer: &Timer<Syscalls>, operation: impl FnOnce() -> T) -> (T, Duration<f64>) {
|
||||||
let before = timestamp(timer);
|
let before = timestamp(timer);
|
||||||
let result = operation();
|
let result = operation();
|
||||||
let after = timestamp(timer);
|
let after = timestamp(timer);
|
||||||
(result, after - before)
|
(result, after - before)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn boot_store(mut storage: TockStorage, erase: bool) -> Store<TockStorage> {
|
fn boot_store(
|
||||||
use persistent_store::Storage;
|
mut storage: Storage<Syscalls, DefaultConfig>,
|
||||||
|
erase: bool,
|
||||||
|
) -> Store<Storage<Syscalls, DefaultConfig>> {
|
||||||
let num_pages = storage.num_pages();
|
let num_pages = storage.num_pages();
|
||||||
if erase {
|
if erase {
|
||||||
for page in 0..num_pages {
|
for page in 0..num_pages {
|
||||||
@@ -55,8 +64,7 @@ struct StorageConfig {
|
|||||||
num_pages: usize,
|
num_pages: usize,
|
||||||
}
|
}
|
||||||
|
|
||||||
fn storage_config(storage: &TockStorage) -> StorageConfig {
|
fn storage_config(storage: &Storage<Syscalls, DefaultConfig>) -> StorageConfig {
|
||||||
use persistent_store::Storage;
|
|
||||||
StorageConfig {
|
StorageConfig {
|
||||||
num_pages: storage.num_pages(),
|
num_pages: storage.num_pages(),
|
||||||
}
|
}
|
||||||
@@ -73,19 +81,19 @@ struct Stat {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn compute_latency(
|
fn compute_latency(
|
||||||
storage: TockStorage,
|
storage: Storage<Syscalls, DefaultConfig>,
|
||||||
timer: &Timer,
|
timer: &Timer<Syscalls>,
|
||||||
num_pages: usize,
|
num_pages: usize,
|
||||||
key_increment: usize,
|
key_increment: usize,
|
||||||
word_length: usize,
|
word_length: usize,
|
||||||
) -> (TockStorage, Stat) {
|
) -> (Storage<Syscalls, DefaultConfig>, Stat) {
|
||||||
let mut stat = Stat {
|
let mut stat = Stat {
|
||||||
key_increment,
|
key_increment,
|
||||||
entry_length: word_length,
|
entry_length: word_length,
|
||||||
..Default::default()
|
..Default::default()
|
||||||
};
|
};
|
||||||
|
|
||||||
let mut console = Console::new();
|
let mut console = Console::<Syscalls>::writer();
|
||||||
writeln!(
|
writeln!(
|
||||||
console,
|
console,
|
||||||
"\nLatency for key_increment={} word_length={}.",
|
"\nLatency for key_increment={} word_length={}.",
|
||||||
@@ -155,20 +163,22 @@ fn compute_latency(
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
let mut with_callback = timer::with_callback(|_, _| {});
|
let mut with_callback = timer::with_callback::<Syscalls, DefaultConfig, _>(|_| {});
|
||||||
let timer = with_callback.init().ok().unwrap();
|
|
||||||
let storage = take_storage().unwrap();
|
let timer = with_callback.init().flex_unwrap();
|
||||||
|
let storage = take_storage::<Syscalls, DefaultConfig>().unwrap();
|
||||||
let config = storage_config(&storage);
|
let config = storage_config(&storage);
|
||||||
let mut stats = Vec::new();
|
let mut stats = Vec::new();
|
||||||
|
let mut console = Console::<Syscalls>::writer();
|
||||||
|
|
||||||
writeln!(Console::new(), "\nRunning 2 tests...").unwrap();
|
writeln!(console, "\nRunning 2 tests...").unwrap();
|
||||||
// Simulate a store full of credentials (of 50 words).
|
// Simulate a store full of credentials (of 50 words).
|
||||||
let (storage, stat) = compute_latency(storage, &timer, config.num_pages, 1, 50);
|
let (storage, stat) = compute_latency(storage, &timer, config.num_pages, 1, 50);
|
||||||
stats.push(stat);
|
stats.push(stat);
|
||||||
// Simulate a store full of increments of a single counter.
|
// Simulate a store full of increments of a single counter.
|
||||||
let (_storage, stat) = compute_latency(storage, &timer, config.num_pages, 0, 1);
|
let (_storage, stat) = compute_latency(storage, &timer, config.num_pages, 0, 1);
|
||||||
stats.push(stat);
|
stats.push(stat);
|
||||||
writeln!(Console::new(), "\nDone.\n").unwrap();
|
writeln!(console, "\nDone.\n").unwrap();
|
||||||
|
|
||||||
const HEADERS: &[&str] = &[
|
const HEADERS: &[&str] = &[
|
||||||
"Overwrite",
|
"Overwrite",
|
||||||
@@ -189,8 +199,8 @@ fn main() {
|
|||||||
format!("{:.1} ms", stat.remove_ms),
|
format!("{:.1} ms", stat.remove_ms),
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
writeln!(Console::new(), "Copy to examples/store_latency.rs:\n").unwrap();
|
writeln!(console, "Copy to examples/store_latency.rs:\n").unwrap();
|
||||||
writeln!(Console::new(), "{:?}", config).unwrap();
|
writeln!(console, "{:?}", config).unwrap();
|
||||||
write_matrix(matrix);
|
write_matrix(matrix);
|
||||||
|
|
||||||
// Results for nrf52840dk_opensk:
|
// Results for nrf52840dk_opensk:
|
||||||
@@ -201,10 +211,11 @@ fn main() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn align(x: &str, n: usize) {
|
fn align(x: &str, n: usize) {
|
||||||
|
let mut console = Console::<Syscalls>::writer();
|
||||||
for _ in 0..n.saturating_sub(x.len()) {
|
for _ in 0..n.saturating_sub(x.len()) {
|
||||||
write!(Console::new(), " ").unwrap();
|
write!(console, " ").unwrap();
|
||||||
}
|
}
|
||||||
write!(Console::new(), "{}", x).unwrap();
|
write!(console, "{}", x).unwrap();
|
||||||
}
|
}
|
||||||
|
|
||||||
fn write_matrix(mut m: Vec<Vec<String>>) {
|
fn write_matrix(mut m: Vec<Vec<String>>) {
|
||||||
@@ -223,6 +234,6 @@ fn write_matrix(mut m: Vec<Vec<String>>) {
|
|||||||
for col in 0..num_cols {
|
for col in 0..num_cols {
|
||||||
align(&row[col], col_len[col] + 2 * (col > 0) as usize);
|
align(&row[col], col_len[col] + 2 * (col > 0) as usize);
|
||||||
}
|
}
|
||||||
writeln!(Console::new()).unwrap();
|
writeln!(Console::<Syscalls>::writer()).unwrap();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
794
fuzz/Cargo.lock
generated
794
fuzz/Cargo.lock
generated
@@ -1,794 +0,0 @@
|
|||||||
# This file is automatically @generated by Cargo.
|
|
||||||
# It is not intended for manual editing.
|
|
||||||
version = 3
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "aho-corasick"
|
|
||||||
version = "0.7.19"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "b4f55bd91a0978cbfd91c457a164bab8b4001c833b7f323132c0a4e1922dd44e"
|
|
||||||
dependencies = [
|
|
||||||
"memchr",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "arbitrary"
|
|
||||||
version = "0.4.7"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "db55d72333851e17d572bec876e390cd3b11eb1ef53ae821dd9f3b653d2b4569"
|
|
||||||
dependencies = [
|
|
||||||
"derive_arbitrary",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "arrayref"
|
|
||||||
version = "0.3.6"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "a4c527152e37cf757a3f78aae5a06fbeefdb07ccc535c980a3208ee3060dd544"
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "autocfg"
|
|
||||||
version = "0.1.8"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "0dde43e75fd43e8a1bf86103336bc699aa8d17ad1be60c76c0bdfd4828e19b78"
|
|
||||||
dependencies = [
|
|
||||||
"autocfg 1.1.0",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "autocfg"
|
|
||||||
version = "1.1.0"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa"
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "bitflags"
|
|
||||||
version = "1.3.2"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "bumpalo"
|
|
||||||
version = "3.8.0"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "8f1e260c3a9040a7c19a12468758f4c16f31a81a1fe087482be9570ec864bb6c"
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "byteorder"
|
|
||||||
version = "1.4.3"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "14c189c53d098945499cdfa7ecc63567cf3886b3332b312a5b4585d8d3a6a610"
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "cc"
|
|
||||||
version = "1.0.73"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "2fff2a6927b3bb87f9595d67196a70493f627687a71d87a0d692242c33f58c11"
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "cfg-if"
|
|
||||||
version = "1.0.0"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "cloudabi"
|
|
||||||
version = "0.0.3"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "ddfc5b9aa5d4507acaf872de71051dfd0e309860e88966e1051e462a077aac4f"
|
|
||||||
dependencies = [
|
|
||||||
"bitflags",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "crypto"
|
|
||||||
version = "0.1.0"
|
|
||||||
dependencies = [
|
|
||||||
"arrayref",
|
|
||||||
"byteorder",
|
|
||||||
"hex",
|
|
||||||
"regex",
|
|
||||||
"ring",
|
|
||||||
"rng256",
|
|
||||||
"serde",
|
|
||||||
"serde_json",
|
|
||||||
"subtle",
|
|
||||||
"untrusted",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "ctap2"
|
|
||||||
version = "1.0.0"
|
|
||||||
dependencies = [
|
|
||||||
"arbitrary",
|
|
||||||
"arrayref",
|
|
||||||
"byteorder",
|
|
||||||
"crypto",
|
|
||||||
"embedded-time",
|
|
||||||
"lang_items",
|
|
||||||
"libtock_core",
|
|
||||||
"libtock_drivers",
|
|
||||||
"openssl",
|
|
||||||
"persistent_store",
|
|
||||||
"rand 0.8.5",
|
|
||||||
"rng256",
|
|
||||||
"sk-cbor",
|
|
||||||
"subtle",
|
|
||||||
"uuid",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "ctap2-fuzz"
|
|
||||||
version = "0.0.0"
|
|
||||||
dependencies = [
|
|
||||||
"fuzz_helper",
|
|
||||||
"libfuzzer-sys",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "derive_arbitrary"
|
|
||||||
version = "0.4.7"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "b1a012b5e473dc912f0db0546a1c9c6a194ce8494feb66fa0237160926f9e0e6"
|
|
||||||
dependencies = [
|
|
||||||
"proc-macro2",
|
|
||||||
"quote",
|
|
||||||
"syn",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "embedded-time"
|
|
||||||
version = "0.12.1"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "d7a4b4d10ac48d08bfe3db7688c402baadb244721f30a77ce360bd24c3dffe58"
|
|
||||||
dependencies = [
|
|
||||||
"num",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "foreign-types"
|
|
||||||
version = "0.3.2"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "f6f339eb8adc052cd2ca78910fda869aefa38d22d5cb648e6485e4d3fc06f3b1"
|
|
||||||
dependencies = [
|
|
||||||
"foreign-types-shared",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "foreign-types-shared"
|
|
||||||
version = "0.1.1"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "00b0228411908ca8685dba7fc2cdd70ec9990a6e753e89b6ac91a84c40fbaf4b"
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "fuchsia-cprng"
|
|
||||||
version = "0.1.1"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "a06f77d526c1a601b7c4cdd98f54b5eaabffc14d5f2f0296febdc7f357c6d3ba"
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "fuzz_helper"
|
|
||||||
version = "0.1.0"
|
|
||||||
dependencies = [
|
|
||||||
"arbitrary",
|
|
||||||
"arrayref",
|
|
||||||
"crypto",
|
|
||||||
"ctap2",
|
|
||||||
"embedded-time",
|
|
||||||
"lang_items",
|
|
||||||
"libtock_drivers",
|
|
||||||
"rng256",
|
|
||||||
"sk-cbor",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "getrandom"
|
|
||||||
version = "0.2.7"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "4eb1a864a501629691edf6c15a593b7a51eebaa1e8468e9ddc623de7c9b58ec6"
|
|
||||||
dependencies = [
|
|
||||||
"cfg-if",
|
|
||||||
"libc",
|
|
||||||
"wasi",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "hex"
|
|
||||||
version = "0.3.2"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "805026a5d0141ffc30abb3be3173848ad46a1b1664fe632428479619a3644d77"
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "itoa"
|
|
||||||
version = "0.4.8"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "b71991ff56294aa922b450139ee08b3bfc70982c6b2c7562771375cf73542dd4"
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "js-sys"
|
|
||||||
version = "0.3.60"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "49409df3e3bf0856b916e2ceaca09ee28e6871cf7d9ce97a692cacfdb2a25a47"
|
|
||||||
dependencies = [
|
|
||||||
"wasm-bindgen",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "lang_items"
|
|
||||||
version = "0.1.0"
|
|
||||||
dependencies = [
|
|
||||||
"libtock_core",
|
|
||||||
"libtock_drivers",
|
|
||||||
"linked_list_allocator",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "libc"
|
|
||||||
version = "0.2.133"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "c0f80d65747a3e43d1596c7c5492d95d5edddaabd45a7fcdb02b95f644164966"
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "libfuzzer-sys"
|
|
||||||
version = "0.3.5"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "fcf184a4b6b274f82a5df6b357da6055d3e82272327bba281c28bbba6f1664ef"
|
|
||||||
dependencies = [
|
|
||||||
"arbitrary",
|
|
||||||
"cc",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "libtock_codegen"
|
|
||||||
version = "0.1.0"
|
|
||||||
dependencies = [
|
|
||||||
"proc-macro2",
|
|
||||||
"quote",
|
|
||||||
"syn",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "libtock_core"
|
|
||||||
version = "0.1.0"
|
|
||||||
dependencies = [
|
|
||||||
"libtock_codegen",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "libtock_drivers"
|
|
||||||
version = "0.1.0"
|
|
||||||
dependencies = [
|
|
||||||
"libtock_core",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "linked_list_allocator"
|
|
||||||
version = "0.8.11"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "822add9edb1860698b79522510da17bef885171f75aa395cff099d770c609c24"
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "log"
|
|
||||||
version = "0.4.17"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "abb12e687cfb44aa40f41fc3978ef76448f9b6038cad6aef4259d3c095a2382e"
|
|
||||||
dependencies = [
|
|
||||||
"cfg-if",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "memchr"
|
|
||||||
version = "2.5.0"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d"
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "num"
|
|
||||||
version = "0.3.1"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "8b7a8e9be5e039e2ff869df49155f1c06bd01ade2117ec783e56ab0932b67a8f"
|
|
||||||
dependencies = [
|
|
||||||
"num-complex",
|
|
||||||
"num-integer",
|
|
||||||
"num-iter",
|
|
||||||
"num-rational",
|
|
||||||
"num-traits",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "num-complex"
|
|
||||||
version = "0.3.1"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "747d632c0c558b87dbabbe6a82f3b4ae03720d0646ac5b7b4dae89394be5f2c5"
|
|
||||||
dependencies = [
|
|
||||||
"num-traits",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "num-integer"
|
|
||||||
version = "0.1.45"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "225d3389fb3509a24c93f5c29eb6bde2586b98d9f016636dff58d7c6f7569cd9"
|
|
||||||
dependencies = [
|
|
||||||
"autocfg 1.1.0",
|
|
||||||
"num-traits",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "num-iter"
|
|
||||||
version = "0.1.43"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "7d03e6c028c5dc5cac6e2dec0efda81fc887605bb3d884578bb6d6bf7514e252"
|
|
||||||
dependencies = [
|
|
||||||
"autocfg 1.1.0",
|
|
||||||
"num-integer",
|
|
||||||
"num-traits",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "num-rational"
|
|
||||||
version = "0.3.2"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "12ac428b1cb17fce6f731001d307d351ec70a6d202fc2e60f7d4c5e42d8f4f07"
|
|
||||||
dependencies = [
|
|
||||||
"autocfg 1.1.0",
|
|
||||||
"num-integer",
|
|
||||||
"num-traits",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "num-traits"
|
|
||||||
version = "0.2.15"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "578ede34cf02f8924ab9447f50c28075b4d3e5b269972345e7e0372b38c6cdcd"
|
|
||||||
dependencies = [
|
|
||||||
"autocfg 1.1.0",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "once_cell"
|
|
||||||
version = "1.14.0"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "2f7254b99e31cad77da24b08ebf628882739a608578bb1bcdfc1f9c21260d7c0"
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "openssl"
|
|
||||||
version = "0.10.41"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "618febf65336490dfcf20b73f885f5651a0c89c64c2d4a8c3662585a70bf5bd0"
|
|
||||||
dependencies = [
|
|
||||||
"bitflags",
|
|
||||||
"cfg-if",
|
|
||||||
"foreign-types",
|
|
||||||
"libc",
|
|
||||||
"once_cell",
|
|
||||||
"openssl-macros",
|
|
||||||
"openssl-sys",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "openssl-macros"
|
|
||||||
version = "0.1.0"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "b501e44f11665960c7e7fcf062c7d96a14ade4aa98116c004b2e37b5be7d736c"
|
|
||||||
dependencies = [
|
|
||||||
"proc-macro2",
|
|
||||||
"quote",
|
|
||||||
"syn",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "openssl-sys"
|
|
||||||
version = "0.9.75"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "e5f9bd0c2710541a3cda73d6f9ac4f1b240de4ae261065d309dbe73d9dceb42f"
|
|
||||||
dependencies = [
|
|
||||||
"autocfg 1.1.0",
|
|
||||||
"cc",
|
|
||||||
"libc",
|
|
||||||
"pkg-config",
|
|
||||||
"vcpkg",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "persistent_store"
|
|
||||||
version = "0.1.0"
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "pkg-config"
|
|
||||||
version = "0.3.25"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "1df8c4ec4b0627e53bdf214615ad287367e482558cf84b109250b37464dc03ae"
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "ppv-lite86"
|
|
||||||
version = "0.2.16"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "eb9f9e6e233e5c4a35559a617bf40a4ec447db2e84c20b55a6f83167b7e57872"
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "proc-macro2"
|
|
||||||
version = "1.0.43"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "0a2ca2c61bc9f3d74d2886294ab7b9853abd9c1ad903a3ac7815c58989bb7bab"
|
|
||||||
dependencies = [
|
|
||||||
"unicode-ident",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "quote"
|
|
||||||
version = "1.0.21"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "bbe448f377a7d6961e30f5955f9b8d106c3f5e449d493ee1b125c1d43c2b5179"
|
|
||||||
dependencies = [
|
|
||||||
"proc-macro2",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "rand"
|
|
||||||
version = "0.6.5"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "6d71dacdc3c88c1fde3885a3be3fbab9f35724e6ce99467f7d9c5026132184ca"
|
|
||||||
dependencies = [
|
|
||||||
"autocfg 0.1.8",
|
|
||||||
"libc",
|
|
||||||
"rand_chacha 0.1.1",
|
|
||||||
"rand_core 0.4.2",
|
|
||||||
"rand_hc",
|
|
||||||
"rand_isaac",
|
|
||||||
"rand_jitter",
|
|
||||||
"rand_os",
|
|
||||||
"rand_pcg",
|
|
||||||
"rand_xorshift",
|
|
||||||
"winapi",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "rand"
|
|
||||||
version = "0.8.5"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404"
|
|
||||||
dependencies = [
|
|
||||||
"libc",
|
|
||||||
"rand_chacha 0.3.1",
|
|
||||||
"rand_core 0.6.4",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "rand_chacha"
|
|
||||||
version = "0.1.1"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "556d3a1ca6600bfcbab7c7c91ccb085ac7fbbcd70e008a98742e7847f4f7bcef"
|
|
||||||
dependencies = [
|
|
||||||
"autocfg 0.1.8",
|
|
||||||
"rand_core 0.3.1",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "rand_chacha"
|
|
||||||
version = "0.3.1"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88"
|
|
||||||
dependencies = [
|
|
||||||
"ppv-lite86",
|
|
||||||
"rand_core 0.6.4",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "rand_core"
|
|
||||||
version = "0.3.1"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "7a6fdeb83b075e8266dcc8762c22776f6877a63111121f5f8c7411e5be7eed4b"
|
|
||||||
dependencies = [
|
|
||||||
"rand_core 0.4.2",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "rand_core"
|
|
||||||
version = "0.4.2"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "9c33a3c44ca05fa6f1807d8e6743f3824e8509beca625669633be0acbdf509dc"
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "rand_core"
|
|
||||||
version = "0.6.4"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c"
|
|
||||||
dependencies = [
|
|
||||||
"getrandom",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "rand_hc"
|
|
||||||
version = "0.1.0"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "7b40677c7be09ae76218dc623efbf7b18e34bced3f38883af07bb75630a21bc4"
|
|
||||||
dependencies = [
|
|
||||||
"rand_core 0.3.1",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "rand_isaac"
|
|
||||||
version = "0.1.1"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "ded997c9d5f13925be2a6fd7e66bf1872597f759fd9dd93513dd7e92e5a5ee08"
|
|
||||||
dependencies = [
|
|
||||||
"rand_core 0.3.1",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "rand_jitter"
|
|
||||||
version = "0.1.4"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "1166d5c91dc97b88d1decc3285bb0a99ed84b05cfd0bc2341bdf2d43fc41e39b"
|
|
||||||
dependencies = [
|
|
||||||
"libc",
|
|
||||||
"rand_core 0.4.2",
|
|
||||||
"winapi",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "rand_os"
|
|
||||||
version = "0.1.3"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "7b75f676a1e053fc562eafbb47838d67c84801e38fc1ba459e8f180deabd5071"
|
|
||||||
dependencies = [
|
|
||||||
"cloudabi",
|
|
||||||
"fuchsia-cprng",
|
|
||||||
"libc",
|
|
||||||
"rand_core 0.4.2",
|
|
||||||
"rdrand",
|
|
||||||
"winapi",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "rand_pcg"
|
|
||||||
version = "0.1.2"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "abf9b09b01790cfe0364f52bf32995ea3c39f4d2dd011eac241d2914146d0b44"
|
|
||||||
dependencies = [
|
|
||||||
"autocfg 0.1.8",
|
|
||||||
"rand_core 0.4.2",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "rand_xorshift"
|
|
||||||
version = "0.1.1"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "cbf7e9e623549b0e21f6e97cf8ecf247c1a8fd2e8a992ae265314300b2455d5c"
|
|
||||||
dependencies = [
|
|
||||||
"rand_core 0.3.1",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "rdrand"
|
|
||||||
version = "0.4.0"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "678054eb77286b51581ba43620cc911abf02758c91f93f479767aed0f90458b2"
|
|
||||||
dependencies = [
|
|
||||||
"rand_core 0.3.1",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "regex"
|
|
||||||
version = "1.6.0"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "4c4eb3267174b8c6c2f654116623910a0fef09c4753f8dd83db29c48a0df988b"
|
|
||||||
dependencies = [
|
|
||||||
"aho-corasick",
|
|
||||||
"memchr",
|
|
||||||
"regex-syntax",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "regex-syntax"
|
|
||||||
version = "0.6.27"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "a3f87b73ce11b1619a3c6332f45341e0047173771e8b8b73f87bfeefb7b56244"
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "ring"
|
|
||||||
version = "0.16.20"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "3053cf52e236a3ed746dfc745aa9cacf1b791d846bdaf412f60a8d7d6e17c8fc"
|
|
||||||
dependencies = [
|
|
||||||
"cc",
|
|
||||||
"libc",
|
|
||||||
"once_cell",
|
|
||||||
"spin",
|
|
||||||
"untrusted",
|
|
||||||
"web-sys",
|
|
||||||
"winapi",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "rng256"
|
|
||||||
version = "0.1.0"
|
|
||||||
dependencies = [
|
|
||||||
"arrayref",
|
|
||||||
"libtock_drivers",
|
|
||||||
"rand 0.6.5",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "ryu"
|
|
||||||
version = "1.0.11"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "4501abdff3ae82a1c1b477a17252eb69cee9e66eb915c1abaa4f44d873df9f09"
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "serde"
|
|
||||||
version = "1.0.144"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "0f747710de3dcd43b88c9168773254e809d8ddbdf9653b84e2554ab219f17860"
|
|
||||||
dependencies = [
|
|
||||||
"serde_derive",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "serde_derive"
|
|
||||||
version = "1.0.144"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "94ed3a816fb1d101812f83e789f888322c34e291f894f19590dc310963e87a00"
|
|
||||||
dependencies = [
|
|
||||||
"proc-macro2",
|
|
||||||
"quote",
|
|
||||||
"syn",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "serde_json"
|
|
||||||
version = "1.0.69"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "e466864e431129c7e0d3476b92f20458e5879919a0596c6472738d9fa2d342f8"
|
|
||||||
dependencies = [
|
|
||||||
"itoa",
|
|
||||||
"ryu",
|
|
||||||
"serde",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "sk-cbor"
|
|
||||||
version = "0.1.2"
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "spin"
|
|
||||||
version = "0.5.2"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "6e63cff320ae2c57904679ba7cb63280a3dc4613885beafb148ee7bf9aa9042d"
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "subtle"
|
|
||||||
version = "2.4.1"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "6bdef32e8150c2a081110b42772ffe7d7c9032b606bc226c8260fd97e0976601"
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "syn"
|
|
||||||
version = "1.0.100"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "52205623b1b0f064a4e71182c3b18ae902267282930c6d5462c91b859668426e"
|
|
||||||
dependencies = [
|
|
||||||
"proc-macro2",
|
|
||||||
"quote",
|
|
||||||
"unicode-ident",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "unicode-ident"
|
|
||||||
version = "1.0.4"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "dcc811dc4066ac62f84f11307873c4850cb653bfa9b1719cee2bd2204a4bc5dd"
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "untrusted"
|
|
||||||
version = "0.7.1"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "a156c684c91ea7d62626509bce3cb4e1d9ed5c4d978f7b4352658f96a4c26b4a"
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "uuid"
|
|
||||||
version = "0.8.2"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "bc5cf98d8186244414c848017f0e2676b3fcb46807f6668a97dfe67359a3c4b7"
|
|
||||||
dependencies = [
|
|
||||||
"getrandom",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "vcpkg"
|
|
||||||
version = "0.2.15"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "accd4ea62f7bb7a82fe23066fb0957d48ef677f6eeb8215f372f52e48bb32426"
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "wasi"
|
|
||||||
version = "0.11.0+wasi-snapshot-preview1"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423"
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "wasm-bindgen"
|
|
||||||
version = "0.2.83"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "eaf9f5aceeec8be17c128b2e93e031fb8a4d469bb9c4ae2d7dc1888b26887268"
|
|
||||||
dependencies = [
|
|
||||||
"cfg-if",
|
|
||||||
"wasm-bindgen-macro",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "wasm-bindgen-backend"
|
|
||||||
version = "0.2.83"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "4c8ffb332579b0557b52d268b91feab8df3615f265d5270fec2a8c95b17c1142"
|
|
||||||
dependencies = [
|
|
||||||
"bumpalo",
|
|
||||||
"log",
|
|
||||||
"once_cell",
|
|
||||||
"proc-macro2",
|
|
||||||
"quote",
|
|
||||||
"syn",
|
|
||||||
"wasm-bindgen-shared",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "wasm-bindgen-macro"
|
|
||||||
version = "0.2.83"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "052be0f94026e6cbc75cdefc9bae13fd6052cdcaf532fa6c45e7ae33a1e6c810"
|
|
||||||
dependencies = [
|
|
||||||
"quote",
|
|
||||||
"wasm-bindgen-macro-support",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "wasm-bindgen-macro-support"
|
|
||||||
version = "0.2.83"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "07bc0c051dc5f23e307b13285f9d75df86bfdf816c5721e573dec1f9b8aa193c"
|
|
||||||
dependencies = [
|
|
||||||
"proc-macro2",
|
|
||||||
"quote",
|
|
||||||
"syn",
|
|
||||||
"wasm-bindgen-backend",
|
|
||||||
"wasm-bindgen-shared",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "wasm-bindgen-shared"
|
|
||||||
version = "0.2.83"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "1c38c045535d93ec4f0b4defec448e4291638ee608530863b1e2ba115d4fff7f"
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "web-sys"
|
|
||||||
version = "0.3.60"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "bcda906d8be16e728fd5adc5b729afad4e444e106ab28cd1c7256e54fa61510f"
|
|
||||||
dependencies = [
|
|
||||||
"js-sys",
|
|
||||||
"wasm-bindgen",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "winapi"
|
|
||||||
version = "0.3.9"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419"
|
|
||||||
dependencies = [
|
|
||||||
"winapi-i686-pc-windows-gnu",
|
|
||||||
"winapi-x86_64-pc-windows-gnu",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "winapi-i686-pc-windows-gnu"
|
|
||||||
version = "0.4.0"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "winapi-x86_64-pc-windows-gnu"
|
|
||||||
version = "0.4.0"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
|
|
||||||
@@ -1,17 +0,0 @@
|
|||||||
[package]
|
|
||||||
name = "fuzz_helper"
|
|
||||||
version = "0.1.0"
|
|
||||||
authors = ["Mingxiao Guo <mingxguo@google.com>"]
|
|
||||||
license = "Apache-2.0"
|
|
||||||
edition = "2018"
|
|
||||||
|
|
||||||
[dependencies]
|
|
||||||
arrayref = "0.3.6"
|
|
||||||
embedded-time = "0.12.1"
|
|
||||||
libtock_drivers = { path = "../../third_party/libtock-drivers" }
|
|
||||||
crypto = { path = "../../libraries/crypto", features = ['std'] }
|
|
||||||
rng256 = { path = "../../libraries/rng256", features = ['std'] }
|
|
||||||
sk-cbor = { path = "../../libraries/cbor" }
|
|
||||||
ctap2 = { path = "../..", features = ["fuzz"] }
|
|
||||||
lang_items = { path = "../../third_party/lang-items", features = ['std'] }
|
|
||||||
arbitrary = { version = "0.4.7", features = ["derive"] }
|
|
||||||
@@ -1,52 +0,0 @@
|
|||||||
diff --git a/deploy.py b/deploy.py
|
|
||||||
index 7f91a2b..f7b1e9a 100755
|
|
||||||
--- a/deploy.py
|
|
||||||
+++ b/deploy.py
|
|
||||||
@@ -156,7 +156,7 @@ SUPPORTED_BOARDS = {
|
|
||||||
),
|
|
||||||
}
|
|
||||||
|
|
||||||
-APP_HEAP_SIZE = 32768
|
|
||||||
+APP_HEAP_SIZE = 16384
|
|
||||||
|
|
||||||
|
|
||||||
def get_supported_boards() -> Tuple[str]:
|
|
||||||
diff --git a/examples/measure_stack.rs b/examples/measure_stack.rs
|
|
||||||
index 88f9ebc..d285a80 100644
|
|
||||||
--- a/examples/measure_stack.rs
|
|
||||||
+++ b/examples/measure_stack.rs
|
|
||||||
@@ -26,7 +26,7 @@ use crypto::{ecdsa, hybrid, sha256};
|
|
||||||
use crypto::sha256::Sha256;
|
|
||||||
use libtock_drivers::console::Console;
|
|
||||||
|
|
||||||
-libtock_core::stack_size! {0x11800}
|
|
||||||
+libtock_core::stack_size! {0x1A000}
|
|
||||||
|
|
||||||
#[inline(never)]
|
|
||||||
fn read_stack_pointer() -> u32 {
|
|
||||||
diff --git a/nrf52840_layout.ld b/nrf52840_layout.ld
|
|
||||||
index 538a2a8..c7dd5e7 100644
|
|
||||||
--- a/nrf52840_layout.ld
|
|
||||||
+++ b/nrf52840_layout.ld
|
|
||||||
@@ -14,7 +14,7 @@ MEMORY {
|
|
||||||
* Any change to STACK_SIZE should be accompanied by a corresponding change to
|
|
||||||
* `elf2tab`'s `--stack` option
|
|
||||||
*/
|
|
||||||
-STACK_SIZE = 71680;
|
|
||||||
+STACK_SIZE = 106496;
|
|
||||||
|
|
||||||
MPU_MIN_ALIGN = 8K;
|
|
||||||
|
|
||||||
diff --git a/patches/tock/07-app-break-fix.patch b/patches/tock/07-app-break-fix.patch
|
|
||||||
index fcf46fd..4048b59 100644
|
|
||||||
--- a/patches/tock/07-app-break-fix.patch
|
|
||||||
+++ b/patches/tock/07-app-break-fix.patch
|
|
||||||
@@ -7,7 +7,7 @@ index c78b1c9fb..2769d0138 100644
|
|
||||||
// The 1.x Tock kernel allocates at least 3 kB to processes, and we need
|
|
||||||
// to ensure that happens as userspace may expect it.
|
|
||||||
- 3 * 1024
|
|
||||||
-+ 70 * 1024
|
|
||||||
++ 104 * 1024
|
|
||||||
|
|
||||||
// TOCK 2.0
|
|
||||||
//
|
|
||||||
158
layout.ld
158
layout.ld
@@ -1,158 +0,0 @@
|
|||||||
/* Userland Generic Layout
|
|
||||||
*
|
|
||||||
* Currently, due to incomplete ROPI-RWPI support in rustc (see
|
|
||||||
* https://github.com/tock/libtock-rs/issues/28), this layout implements static
|
|
||||||
* linking. An application init script must define the FLASH and SRAM address
|
|
||||||
* ranges as well as MPU_MIN_ALIGN before including this layout file.
|
|
||||||
*
|
|
||||||
* Here is a an example application linker script to get started:
|
|
||||||
* MEMORY {
|
|
||||||
* /* FLASH memory region must start immediately *after* the Tock
|
|
||||||
* * Binary Format headers, which means you need to offset the
|
|
||||||
* * beginning of FLASH memory region relative to where the
|
|
||||||
* * application is loaded.
|
|
||||||
* FLASH (rx) : ORIGIN = 0x10030, LENGTH = 0x0FFD0
|
|
||||||
* SRAM (RWX) : ORIGIN = 0x20000, LENGTH = 0x10000
|
|
||||||
* }
|
|
||||||
* MPU_MIN_ALIGN = 8K;
|
|
||||||
* INCLUDE ../libtock-rs/layout.ld
|
|
||||||
*/
|
|
||||||
|
|
||||||
ENTRY(_start)
|
|
||||||
|
|
||||||
SECTIONS {
|
|
||||||
/* Section for just the app crt0 header.
|
|
||||||
* This must be first so that the app can find it.
|
|
||||||
*/
|
|
||||||
/* Runtime setup logic. The crt0_header symbol is used by the entry point
|
|
||||||
* assembly. We have to include start here rather than .text because
|
|
||||||
* otherwise elf2tab fails to recognize that the process binary's flash
|
|
||||||
* region should start at the beginning of .start.
|
|
||||||
*/
|
|
||||||
.start :
|
|
||||||
{
|
|
||||||
_beginning = .; /* Start of the app in flash. */
|
|
||||||
crt0_header = .;
|
|
||||||
/**
|
|
||||||
* Populate the header expected by `crt0`:
|
|
||||||
*
|
|
||||||
* struct hdr {
|
|
||||||
* uint32_t got_sym_start;
|
|
||||||
* uint32_t got_start;
|
|
||||||
* uint32_t got_size;
|
|
||||||
* uint32_t data_sym_start;
|
|
||||||
* uint32_t data_start;
|
|
||||||
* uint32_t data_size;
|
|
||||||
* uint32_t bss_start;
|
|
||||||
* uint32_t bss_size;
|
|
||||||
* uint32_t reldata_start;
|
|
||||||
* uint32_t stack_size;
|
|
||||||
* };
|
|
||||||
*/
|
|
||||||
/* Offset of GOT symbols in flash */
|
|
||||||
LONG(LOADADDR(.got) - _beginning);
|
|
||||||
/* Offset of GOT section in memory */
|
|
||||||
LONG(_got);
|
|
||||||
/* Size of GOT section */
|
|
||||||
LONG(SIZEOF(.got));
|
|
||||||
/* Offset of data symbols in flash */
|
|
||||||
LONG(LOADADDR(.data) - _beginning);
|
|
||||||
/* Offset of data section in memory */
|
|
||||||
LONG(_data);
|
|
||||||
/* Size of data section */
|
|
||||||
LONG(SIZEOF(.data));
|
|
||||||
/* Offset of BSS section in memory */
|
|
||||||
LONG(_bss);
|
|
||||||
/* Size of BSS section */
|
|
||||||
LONG(SIZEOF(.bss));
|
|
||||||
/* First address offset after program flash, where elf2tab places
|
|
||||||
* .rel.data section */
|
|
||||||
LONG(LOADADDR(.endflash) - _beginning);
|
|
||||||
/* The size of the stack requested by this application */
|
|
||||||
LONG(_stack_top_aligned - _sstack);
|
|
||||||
/* Pad the header out to a multiple of 32 bytes so there is not a gap
|
|
||||||
* between the header and subsequent .data section. It's unclear why,
|
|
||||||
* but LLD is aligning sections to a multiple of 32 bytes. */
|
|
||||||
. = ALIGN(32);
|
|
||||||
|
|
||||||
*(.start)
|
|
||||||
} > FLASH =0xFFFFFFFF
|
|
||||||
|
|
||||||
/* Text section, Code! */
|
|
||||||
.text :
|
|
||||||
{
|
|
||||||
. = ALIGN(4);
|
|
||||||
_text = .;
|
|
||||||
*(.text*)
|
|
||||||
*(.rodata*)
|
|
||||||
KEEP (*(.syscalls))
|
|
||||||
*(.ARM.extab*)
|
|
||||||
. = ALIGN(4); /* Make sure we're word-aligned here */
|
|
||||||
_etext = .;
|
|
||||||
} > FLASH =0xFFFFFFFF
|
|
||||||
|
|
||||||
/* Application stack */
|
|
||||||
.stack (NOLOAD) :
|
|
||||||
{
|
|
||||||
/* elf2tab requires that the `_sram_origin` symbol be present to
|
|
||||||
* mark the first address in the SRAM memory. Since ELF files do
|
|
||||||
* not really need to specify this address as they only care about
|
|
||||||
* loading into flash, we need to manually mark this address for
|
|
||||||
* elf2tab. elf2tab will use it to add a fixed address header in the
|
|
||||||
* TBF header if needed.
|
|
||||||
*/
|
|
||||||
_sram_origin = .;
|
|
||||||
_sstack = .;
|
|
||||||
KEEP(*(.stack_buffer))
|
|
||||||
_stack_top_unaligned = .;
|
|
||||||
. = ALIGN(8);
|
|
||||||
_stack_top_aligned = .;
|
|
||||||
} > SRAM
|
|
||||||
|
|
||||||
/* Data section, static initialized variables
|
|
||||||
* Note: This is placed in Flash after the text section, but needs to be
|
|
||||||
* moved to SRAM at runtime
|
|
||||||
*/
|
|
||||||
.data : AT (_etext)
|
|
||||||
{
|
|
||||||
. = ALIGN(4); /* Make sure we're word-aligned here */
|
|
||||||
_data = .;
|
|
||||||
KEEP(*(.data*))
|
|
||||||
*(.sdata*) /* RISC-V small-pointer data section */
|
|
||||||
. = ALIGN(4); /* Make sure we're word-aligned at the end of flash */
|
|
||||||
} > SRAM
|
|
||||||
|
|
||||||
/* Global Offset Table */
|
|
||||||
.got :
|
|
||||||
{
|
|
||||||
. = ALIGN(4); /* Make sure we're word-aligned here */
|
|
||||||
_got = .;
|
|
||||||
*(.got*)
|
|
||||||
*(.got.plt*)
|
|
||||||
. = ALIGN(4);
|
|
||||||
} > SRAM
|
|
||||||
|
|
||||||
/* BSS section, static uninitialized variables */
|
|
||||||
.bss :
|
|
||||||
{
|
|
||||||
. = ALIGN(4); /* Make sure we're word-aligned here */
|
|
||||||
_bss = .;
|
|
||||||
KEEP(*(.bss* .sbss*))
|
|
||||||
*(COMMON)
|
|
||||||
. = ALIGN(4);
|
|
||||||
} > SRAM
|
|
||||||
|
|
||||||
/* End of flash. */
|
|
||||||
.endflash :
|
|
||||||
{
|
|
||||||
} > FLASH
|
|
||||||
|
|
||||||
/* Sections we do not need. */
|
|
||||||
/DISCARD/ :
|
|
||||||
{
|
|
||||||
*(.ARM.exidx .eh_frame)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ASSERT((_stack_top_aligned - _stack_top_unaligned) == 0, "
|
|
||||||
STACK_SIZE must be 8 byte multiple")
|
|
||||||
7
libraries/cbor/Cargo.lock
generated
7
libraries/cbor/Cargo.lock
generated
@@ -1,7 +0,0 @@
|
|||||||
# This file is automatically @generated by Cargo.
|
|
||||||
# It is not intended for manual editing.
|
|
||||||
version = 3
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "sk-cbor"
|
|
||||||
version = "0.1.2"
|
|
||||||
@@ -13,41 +13,26 @@ This crate implements Concise Binary Object Representation (CBOR) from [RFC
|
|||||||
|
|
||||||
```rust
|
```rust
|
||||||
fn main() {
|
fn main() {
|
||||||
// Build a CBOR object with various different types included. Note that this
|
// Build a CBOR object with the crate's convenience macros. Note that this
|
||||||
// object is not built in canonical order.
|
// object is not built in canonical order.
|
||||||
let manual_object = Value::Map(vec![
|
let map_object = cbor_map! {
|
||||||
(
|
|
||||||
Value::Unsigned(1),
|
|
||||||
Value::Array(vec![Value::Unsigned(2), Value::Unsigned(3)]),
|
|
||||||
),
|
|
||||||
(
|
|
||||||
Value::TextString("tstr".to_owned()),
|
|
||||||
Value::ByteString(vec![1, 2, 3]),
|
|
||||||
),
|
|
||||||
(Value::Negative(-2), Value::Simple(SimpleValue::NullValue)),
|
|
||||||
(Value::Unsigned(3), Value::Simple(SimpleValue::TrueValue)),
|
|
||||||
]);
|
|
||||||
|
|
||||||
// Build the same object using the crate's convenience macros.
|
|
||||||
let macro_object = cbor_map! {
|
|
||||||
1 => cbor_array![2, 3],
|
1 => cbor_array![2, 3],
|
||||||
"tstr" => cbor_bytes!(vec![1, 2, 3]),
|
"tstr" => cbor_bytes!(vec![1, 2, 3]),
|
||||||
-2 => cbor_null!(),
|
-2 => cbor_null!(),
|
||||||
3 => cbor_true!(),
|
3 => cbor_true!(),
|
||||||
};
|
};
|
||||||
|
|
||||||
assert_eq!(manual_object, macro_object);
|
println!("Object {:?}", map_object);
|
||||||
println!("Object {:?}", manual_object);
|
|
||||||
|
|
||||||
// Serialize to bytes.
|
// Serialize to bytes.
|
||||||
let mut manual_data = vec![];
|
let mut map_data = vec![];
|
||||||
sk_cbor::writer::write(manual_object, &mut manual_data);
|
sk_cbor::writer::write(map_object, &mut map_data).unwrap();
|
||||||
let hex_manual_data = hexify(&manual_data);
|
let hex_map_data = hex::encode(&map_data);
|
||||||
|
|
||||||
// Serialized version is in canonical order.
|
// Serialized version is in canonical order.
|
||||||
println!("Serializes to {}", hex_manual_data);
|
println!("Serializes to {}", hex_map_data);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
hex_manual_data,
|
hex_map_data,
|
||||||
concat!(
|
concat!(
|
||||||
"a4", // 4-map
|
"a4", // 4-map
|
||||||
"01", // int(1) =>
|
"01", // int(1) =>
|
||||||
@@ -63,7 +48,7 @@ fn main() {
|
|||||||
|
|
||||||
// Convert back to an object. This is different than the original object,
|
// Convert back to an object. This is different than the original object,
|
||||||
// because the map is now in canonical order.
|
// because the map is now in canonical order.
|
||||||
let recovered_object = sk_cbor::reader::read(&manual_data).unwrap();
|
let recovered_object = sk_cbor::reader::read(&map_data).unwrap();
|
||||||
println!("Deserializes to {:?}", recovered_object);
|
println!("Deserializes to {:?}", recovered_object);
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|||||||
@@ -18,7 +18,7 @@
|
|||||||
|
|
||||||
extern crate alloc;
|
extern crate alloc;
|
||||||
|
|
||||||
use sk_cbor::values::{SimpleValue, Value};
|
use sk_cbor::values::Value;
|
||||||
use sk_cbor::{cbor_array, cbor_bytes, cbor_map, cbor_null, cbor_true};
|
use sk_cbor::{cbor_array, cbor_bytes, cbor_map, cbor_null, cbor_true};
|
||||||
|
|
||||||
fn hexify(data: &[u8]) -> String {
|
fn hexify(data: &[u8]) -> String {
|
||||||
@@ -32,17 +32,14 @@ fn hexify(data: &[u8]) -> String {
|
|||||||
fn main() {
|
fn main() {
|
||||||
// Build a CBOR object with various different types included. Note that this
|
// Build a CBOR object with various different types included. Note that this
|
||||||
// object is not built in canonical order.
|
// object is not built in canonical order.
|
||||||
let manual_object = Value::Map(vec![
|
let manual_object = Value::map(vec![
|
||||||
(
|
(
|
||||||
Value::Unsigned(1),
|
Value::from(1),
|
||||||
Value::Array(vec![Value::Unsigned(2), Value::Unsigned(3)]),
|
Value::array(vec![Value::from(2), Value::from(3)]),
|
||||||
),
|
),
|
||||||
(
|
(Value::from("tstr".to_owned()), Value::from(vec![1, 2, 3])),
|
||||||
Value::TextString("tstr".to_owned()),
|
(Value::from(-2), Value::null_value()),
|
||||||
Value::ByteString(vec![1, 2, 3]),
|
(Value::from(3), Value::bool_value(true)),
|
||||||
),
|
|
||||||
(Value::Negative(-2), Value::Simple(SimpleValue::NullValue)),
|
|
||||||
(Value::Unsigned(3), Value::Simple(SimpleValue::TrueValue)),
|
|
||||||
]);
|
]);
|
||||||
|
|
||||||
// Build the same object using the crate's convenience macros.
|
// Build the same object using the crate's convenience macros.
|
||||||
|
|||||||
3
libraries/cbor/fuzz/.gitignore
vendored
Normal file
3
libraries/cbor/fuzz/.gitignore
vendored
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
/artifacts/
|
||||||
|
/corpus/
|
||||||
|
/target/
|
||||||
37
libraries/cbor/fuzz/Cargo.lock
generated
37
libraries/cbor/fuzz/Cargo.lock
generated
@@ -1,37 +0,0 @@
|
|||||||
# This file is automatically @generated by Cargo.
|
|
||||||
# It is not intended for manual editing.
|
|
||||||
version = 3
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "arbitrary"
|
|
||||||
version = "0.4.7"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "db55d72333851e17d572bec876e390cd3b11eb1ef53ae821dd9f3b653d2b4569"
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "cc"
|
|
||||||
version = "1.0.73"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "2fff2a6927b3bb87f9595d67196a70493f627687a71d87a0d692242c33f58c11"
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "libfuzzer-sys"
|
|
||||||
version = "0.3.5"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "fcf184a4b6b274f82a5df6b357da6055d3e82272327bba281c28bbba6f1664ef"
|
|
||||||
dependencies = [
|
|
||||||
"arbitrary",
|
|
||||||
"cc",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "sk-cbor"
|
|
||||||
version = "0.1.2"
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "sk-cbor-fuzz"
|
|
||||||
version = "0.0.0"
|
|
||||||
dependencies = [
|
|
||||||
"libfuzzer-sys",
|
|
||||||
"sk-cbor",
|
|
||||||
]
|
|
||||||
@@ -22,5 +22,5 @@ pub mod values;
|
|||||||
pub mod writer;
|
pub mod writer;
|
||||||
|
|
||||||
pub use self::reader::read;
|
pub use self::reader::read;
|
||||||
pub use self::values::{SimpleValue, Value};
|
pub use self::values::Value;
|
||||||
pub use self::writer::write;
|
pub use self::writer::write;
|
||||||
|
|||||||
@@ -139,9 +139,12 @@ macro_rules! assert_sorted_keys {
|
|||||||
///
|
///
|
||||||
/// Keys and values are expressions and converted into CBOR Keys and Values.
|
/// Keys and values are expressions and converted into CBOR Keys and Values.
|
||||||
/// The syntax for these pairs is `key_expression => value_expression,`.
|
/// The syntax for these pairs is `key_expression => value_expression,`.
|
||||||
/// Duplicate keys will lead to invalid CBOR, i.e. writing these values fails.
|
|
||||||
/// Keys do not have to be sorted.
|
/// Keys do not have to be sorted.
|
||||||
///
|
///
|
||||||
|
/// # Panics
|
||||||
|
///
|
||||||
|
/// You may not call this function with identical keys in its argument.
|
||||||
|
///
|
||||||
/// Example usage:
|
/// Example usage:
|
||||||
///
|
///
|
||||||
/// ```rust
|
/// ```rust
|
||||||
@@ -168,7 +171,7 @@ macro_rules! cbor_map {
|
|||||||
$(
|
$(
|
||||||
_map.push(($key.into_cbor_value(), $value.into_cbor_value()));
|
_map.push(($key.into_cbor_value(), $value.into_cbor_value()));
|
||||||
)*
|
)*
|
||||||
$crate::values::Value::Map(_map)
|
$crate::values::Value::map(_map)
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@@ -214,7 +217,7 @@ macro_rules! cbor_map_options {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
)*
|
)*
|
||||||
$crate::values::Value::Map(_map)
|
$crate::values::Value::map(_map)
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@@ -223,7 +226,7 @@ macro_rules! cbor_map_options {
|
|||||||
#[macro_export]
|
#[macro_export]
|
||||||
macro_rules! cbor_map_collection {
|
macro_rules! cbor_map_collection {
|
||||||
( $tree:expr ) => {{
|
( $tree:expr ) => {{
|
||||||
$crate::values::Value::from($tree)
|
$crate::values::Value::map($tree)
|
||||||
}};
|
}};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -250,7 +253,7 @@ macro_rules! cbor_array {
|
|||||||
// The import is unused if the list is empty.
|
// The import is unused if the list is empty.
|
||||||
#[allow(unused_imports)]
|
#[allow(unused_imports)]
|
||||||
use $crate::values::IntoCborValue;
|
use $crate::values::IntoCborValue;
|
||||||
$crate::values::Value::Array(vec![ $( $value.into_cbor_value(), )* ])
|
$crate::values::Value::array(vec![ $( $value.into_cbor_value(), )* ])
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@@ -260,7 +263,7 @@ macro_rules! cbor_array {
|
|||||||
macro_rules! cbor_array_vec {
|
macro_rules! cbor_array_vec {
|
||||||
( $vec:expr ) => {{
|
( $vec:expr ) => {{
|
||||||
use $crate::values::IntoCborValue;
|
use $crate::values::IntoCborValue;
|
||||||
$crate::values::Value::Array($vec.into_iter().map(|x| x.into_cbor_value()).collect())
|
$crate::values::Value::array($vec.into_iter().map(|x| x.into_cbor_value()).collect())
|
||||||
}};
|
}};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -268,7 +271,7 @@ macro_rules! cbor_array_vec {
|
|||||||
#[macro_export]
|
#[macro_export]
|
||||||
macro_rules! cbor_true {
|
macro_rules! cbor_true {
|
||||||
( ) => {
|
( ) => {
|
||||||
$crate::values::Value::Simple($crate::values::SimpleValue::TrueValue)
|
$crate::values::Value::bool_value(true)
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -276,7 +279,7 @@ macro_rules! cbor_true {
|
|||||||
#[macro_export]
|
#[macro_export]
|
||||||
macro_rules! cbor_false {
|
macro_rules! cbor_false {
|
||||||
( ) => {
|
( ) => {
|
||||||
$crate::values::Value::Simple($crate::values::SimpleValue::FalseValue)
|
$crate::values::Value::bool_value(false)
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -284,7 +287,7 @@ macro_rules! cbor_false {
|
|||||||
#[macro_export]
|
#[macro_export]
|
||||||
macro_rules! cbor_null {
|
macro_rules! cbor_null {
|
||||||
( ) => {
|
( ) => {
|
||||||
$crate::values::Value::Simple($crate::values::SimpleValue::NullValue)
|
$crate::values::Value::null_value()
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -292,7 +295,7 @@ macro_rules! cbor_null {
|
|||||||
#[macro_export]
|
#[macro_export]
|
||||||
macro_rules! cbor_undefined {
|
macro_rules! cbor_undefined {
|
||||||
( ) => {
|
( ) => {
|
||||||
$crate::values::Value::Simple($crate::values::SimpleValue::Undefined)
|
$crate::values::Value::undefined()
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -308,7 +311,7 @@ macro_rules! cbor_bool {
|
|||||||
#[macro_export]
|
#[macro_export]
|
||||||
macro_rules! cbor_unsigned {
|
macro_rules! cbor_unsigned {
|
||||||
( $x:expr ) => {
|
( $x:expr ) => {
|
||||||
$crate::values::Value::Unsigned($x)
|
$crate::values::Value::unsigned($x as u64)
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -316,7 +319,7 @@ macro_rules! cbor_unsigned {
|
|||||||
#[macro_export]
|
#[macro_export]
|
||||||
macro_rules! cbor_int {
|
macro_rules! cbor_int {
|
||||||
( $x:expr ) => {
|
( $x:expr ) => {
|
||||||
$crate::values::Value::integer($x)
|
$crate::values::Value::integer($x as i64)
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -324,7 +327,7 @@ macro_rules! cbor_int {
|
|||||||
#[macro_export]
|
#[macro_export]
|
||||||
macro_rules! cbor_text {
|
macro_rules! cbor_text {
|
||||||
( $x:expr ) => {
|
( $x:expr ) => {
|
||||||
$crate::values::Value::TextString($x.into())
|
$crate::values::Value::text_string($x.into())
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -332,7 +335,7 @@ macro_rules! cbor_text {
|
|||||||
#[macro_export]
|
#[macro_export]
|
||||||
macro_rules! cbor_bytes {
|
macro_rules! cbor_bytes {
|
||||||
( $x:expr ) => {
|
( $x:expr ) => {
|
||||||
$crate::values::Value::ByteString($x)
|
$crate::values::Value::byte_string($x)
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -340,7 +343,7 @@ macro_rules! cbor_bytes {
|
|||||||
#[macro_export]
|
#[macro_export]
|
||||||
macro_rules! cbor_tagged {
|
macro_rules! cbor_tagged {
|
||||||
( $t:expr, $x: expr ) => {
|
( $t:expr, $x: expr ) => {
|
||||||
$crate::values::Value::Tag($t, ::alloc::boxed::Box::new($x))
|
$crate::values::Value::tag($t, $x)
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -362,41 +365,41 @@ macro_rules! cbor_bytes_lit {
|
|||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod test {
|
mod test {
|
||||||
use super::super::values::{SimpleValue, Value};
|
use super::super::values::Value;
|
||||||
use alloc::string::String;
|
use alloc::string::String;
|
||||||
use alloc::vec;
|
use alloc::vec;
|
||||||
use alloc::vec::Vec;
|
use alloc::vec::Vec;
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_cbor_simple_values() {
|
fn test_cbor_simple_values() {
|
||||||
assert_eq!(cbor_true!(), Value::Simple(SimpleValue::TrueValue));
|
assert_eq!(cbor_true!(), Value::bool_value(true));
|
||||||
assert_eq!(cbor_false!(), Value::Simple(SimpleValue::FalseValue));
|
assert_eq!(cbor_false!(), Value::bool_value(false));
|
||||||
assert_eq!(cbor_null!(), Value::Simple(SimpleValue::NullValue));
|
assert_eq!(cbor_null!(), Value::null_value());
|
||||||
assert_eq!(cbor_undefined!(), Value::Simple(SimpleValue::Undefined));
|
assert_eq!(cbor_undefined!(), Value::undefined());
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_cbor_bool() {
|
fn test_cbor_bool() {
|
||||||
assert_eq!(cbor_bool!(true), Value::Simple(SimpleValue::TrueValue));
|
assert_eq!(cbor_bool!(true), Value::bool_value(true));
|
||||||
assert_eq!(cbor_bool!(false), Value::Simple(SimpleValue::FalseValue));
|
assert_eq!(cbor_bool!(false), Value::bool_value(false));
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_cbor_int_unsigned() {
|
fn test_cbor_int_unsigned() {
|
||||||
assert_eq!(cbor_int!(0), Value::Unsigned(0));
|
assert_eq!(cbor_int!(0), Value::from(0));
|
||||||
assert_eq!(cbor_int!(1), Value::Unsigned(1));
|
assert_eq!(cbor_int!(1), Value::from(1));
|
||||||
assert_eq!(cbor_int!(123456), Value::Unsigned(123456));
|
assert_eq!(cbor_int!(123456), Value::from(123456));
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
cbor_int!(core::i64::MAX),
|
cbor_int!(core::i64::MAX),
|
||||||
Value::Unsigned(core::i64::MAX as u64)
|
Value::from(core::i64::MAX as u64)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_cbor_int_negative() {
|
fn test_cbor_int_negative() {
|
||||||
assert_eq!(cbor_int!(-1), Value::Negative(-1));
|
assert_eq!(cbor_int!(-1), Value::from(-1));
|
||||||
assert_eq!(cbor_int!(-123456), Value::Negative(-123456));
|
assert_eq!(cbor_int!(-123456), Value::from(-123456));
|
||||||
assert_eq!(cbor_int!(core::i64::MIN), Value::Negative(core::i64::MIN));
|
assert_eq!(cbor_int!(core::i64::MIN), Value::from(core::i64::MIN));
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
@@ -413,17 +416,17 @@ mod test {
|
|||||||
core::i64::MAX,
|
core::i64::MAX,
|
||||||
core::u64::MAX,
|
core::u64::MAX,
|
||||||
];
|
];
|
||||||
let b = Value::Array(vec![
|
let b = Value::array(vec![
|
||||||
Value::Negative(core::i64::MIN),
|
Value::from(core::i64::MIN),
|
||||||
Value::Negative(core::i32::MIN as i64),
|
Value::from(core::i32::MIN as i64),
|
||||||
Value::Negative(-123456),
|
Value::from(-123456),
|
||||||
Value::Negative(-1),
|
Value::from(-1),
|
||||||
Value::Unsigned(0),
|
Value::from(0),
|
||||||
Value::Unsigned(1),
|
Value::from(1),
|
||||||
Value::Unsigned(123456),
|
Value::from(123456),
|
||||||
Value::Unsigned(core::i32::MAX as u64),
|
Value::from(core::i32::MAX as u64),
|
||||||
Value::Unsigned(core::i64::MAX as u64),
|
Value::from(core::i64::MAX as u64),
|
||||||
Value::Unsigned(core::u64::MAX),
|
Value::from(core::u64::MAX),
|
||||||
]);
|
]);
|
||||||
assert_eq!(a, b);
|
assert_eq!(a, b);
|
||||||
}
|
}
|
||||||
@@ -442,22 +445,17 @@ mod test {
|
|||||||
cbor_map! {},
|
cbor_map! {},
|
||||||
cbor_map! {2 => 3},
|
cbor_map! {2 => 3},
|
||||||
];
|
];
|
||||||
let b = Value::Array(vec![
|
let b = Value::array(vec![
|
||||||
Value::Negative(-123),
|
Value::from(-123),
|
||||||
Value::Unsigned(456),
|
Value::from(456),
|
||||||
Value::Simple(SimpleValue::TrueValue),
|
Value::bool_value(true),
|
||||||
Value::Simple(SimpleValue::NullValue),
|
Value::null_value(),
|
||||||
Value::TextString(String::from("foo")),
|
Value::from(String::from("foo")),
|
||||||
Value::ByteString(b"bar".to_vec()),
|
Value::from(b"bar".to_vec()),
|
||||||
Value::Array(Vec::new()),
|
Value::array(Vec::new()),
|
||||||
Value::Array(vec![Value::Unsigned(0), Value::Unsigned(1)]),
|
Value::array(vec![Value::from(0), Value::from(1)]),
|
||||||
Value::Map(Vec::new()),
|
Value::map(Vec::new()),
|
||||||
Value::Map(
|
Value::map([(Value::from(2), Value::from(3))].iter().cloned().collect()),
|
||||||
[(Value::Unsigned(2), Value::Unsigned(3))]
|
|
||||||
.iter()
|
|
||||||
.cloned()
|
|
||||||
.collect(),
|
|
||||||
),
|
|
||||||
]);
|
]);
|
||||||
assert_eq!(a, b);
|
assert_eq!(a, b);
|
||||||
}
|
}
|
||||||
@@ -465,18 +463,18 @@ mod test {
|
|||||||
#[test]
|
#[test]
|
||||||
fn test_cbor_array_vec_empty() {
|
fn test_cbor_array_vec_empty() {
|
||||||
let a = cbor_array_vec!(Vec::<bool>::new());
|
let a = cbor_array_vec!(Vec::<bool>::new());
|
||||||
let b = Value::Array(Vec::new());
|
let b = Value::array(Vec::new());
|
||||||
assert_eq!(a, b);
|
assert_eq!(a, b);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_cbor_array_vec_int() {
|
fn test_cbor_array_vec_int() {
|
||||||
let a = cbor_array_vec!(vec![1, 2, 3, 4]);
|
let a = cbor_array_vec!(vec![1, 2, 3, 4]);
|
||||||
let b = Value::Array(vec![
|
let b = Value::array(vec![
|
||||||
Value::Unsigned(1),
|
Value::from(1),
|
||||||
Value::Unsigned(2),
|
Value::from(2),
|
||||||
Value::Unsigned(3),
|
Value::from(3),
|
||||||
Value::Unsigned(4),
|
Value::from(4),
|
||||||
]);
|
]);
|
||||||
assert_eq!(a, b);
|
assert_eq!(a, b);
|
||||||
}
|
}
|
||||||
@@ -484,10 +482,10 @@ mod test {
|
|||||||
#[test]
|
#[test]
|
||||||
fn test_cbor_array_vec_text() {
|
fn test_cbor_array_vec_text() {
|
||||||
let a = cbor_array_vec!(vec!["a", "b", "c"]);
|
let a = cbor_array_vec!(vec!["a", "b", "c"]);
|
||||||
let b = Value::Array(vec![
|
let b = Value::array(vec![
|
||||||
Value::TextString(String::from("a")),
|
Value::from(String::from("a")),
|
||||||
Value::TextString(String::from("b")),
|
Value::from(String::from("b")),
|
||||||
Value::TextString(String::from("c")),
|
Value::from(String::from("c")),
|
||||||
]);
|
]);
|
||||||
assert_eq!(a, b);
|
assert_eq!(a, b);
|
||||||
}
|
}
|
||||||
@@ -495,10 +493,10 @@ mod test {
|
|||||||
#[test]
|
#[test]
|
||||||
fn test_cbor_array_vec_bytes() {
|
fn test_cbor_array_vec_bytes() {
|
||||||
let a = cbor_array_vec!(vec![b"a", b"b", b"c"]);
|
let a = cbor_array_vec!(vec![b"a", b"b", b"c"]);
|
||||||
let b = Value::Array(vec![
|
let b = Value::array(vec![
|
||||||
Value::ByteString(b"a".to_vec()),
|
Value::from(b"a".to_vec()),
|
||||||
Value::ByteString(b"b".to_vec()),
|
Value::from(b"b".to_vec()),
|
||||||
Value::ByteString(b"c".to_vec()),
|
Value::from(b"c".to_vec()),
|
||||||
]);
|
]);
|
||||||
assert_eq!(a, b);
|
assert_eq!(a, b);
|
||||||
}
|
}
|
||||||
@@ -506,46 +504,35 @@ mod test {
|
|||||||
#[test]
|
#[test]
|
||||||
fn test_cbor_map() {
|
fn test_cbor_map() {
|
||||||
let a = cbor_map! {
|
let a = cbor_map! {
|
||||||
-1 => -23,
|
|
||||||
4 => 56,
|
4 => 56,
|
||||||
"foo" => true,
|
|
||||||
b"bar" => cbor_null!(),
|
|
||||||
5 => "foo",
|
5 => "foo",
|
||||||
6 => b"bar",
|
6 => b"bar",
|
||||||
7 => cbor_array![],
|
7 => cbor_array![],
|
||||||
8 => cbor_array![0, 1],
|
8 => cbor_array![0, 1],
|
||||||
9 => cbor_map!{},
|
9 => cbor_map!{},
|
||||||
10 => cbor_map!{2 => 3},
|
10 => cbor_map!{2 => 3},
|
||||||
|
-1 => -23,
|
||||||
|
b"bar" => cbor_null!(),
|
||||||
|
"foo" => true,
|
||||||
};
|
};
|
||||||
let b = Value::Map(
|
let b = Value::map(
|
||||||
[
|
[
|
||||||
(Value::Negative(-1), Value::Negative(-23)),
|
(Value::from(4), Value::from(56)),
|
||||||
(Value::Unsigned(4), Value::Unsigned(56)),
|
(Value::from(5), Value::from(String::from("foo"))),
|
||||||
|
(Value::from(6), Value::from(b"bar".to_vec())),
|
||||||
|
(Value::from(7), Value::array(Vec::new())),
|
||||||
(
|
(
|
||||||
Value::TextString(String::from("foo")),
|
Value::from(8),
|
||||||
Value::Simple(SimpleValue::TrueValue),
|
Value::array(vec![Value::from(0), Value::from(1)]),
|
||||||
),
|
),
|
||||||
|
(Value::from(9), Value::map(Vec::new())),
|
||||||
(
|
(
|
||||||
Value::ByteString(b"bar".to_vec()),
|
Value::from(10),
|
||||||
Value::Simple(SimpleValue::NullValue),
|
Value::map([(Value::from(2), Value::from(3))].iter().cloned().collect()),
|
||||||
),
|
|
||||||
(Value::Unsigned(5), Value::TextString(String::from("foo"))),
|
|
||||||
(Value::Unsigned(6), Value::ByteString(b"bar".to_vec())),
|
|
||||||
(Value::Unsigned(7), Value::Array(Vec::new())),
|
|
||||||
(
|
|
||||||
Value::Unsigned(8),
|
|
||||||
Value::Array(vec![Value::Unsigned(0), Value::Unsigned(1)]),
|
|
||||||
),
|
|
||||||
(Value::Unsigned(9), Value::Map(Vec::new())),
|
|
||||||
(
|
|
||||||
Value::Unsigned(10),
|
|
||||||
Value::Map(
|
|
||||||
[(Value::Unsigned(2), Value::Unsigned(3))]
|
|
||||||
.iter()
|
|
||||||
.cloned()
|
|
||||||
.collect(),
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
|
(Value::from(-1), Value::from(-23)),
|
||||||
|
(Value::from(b"bar".to_vec()), Value::null_value()),
|
||||||
|
(Value::from(String::from("foo")), Value::bool_value(true)),
|
||||||
]
|
]
|
||||||
.iter()
|
.iter()
|
||||||
.cloned()
|
.cloned()
|
||||||
@@ -557,54 +544,43 @@ mod test {
|
|||||||
#[test]
|
#[test]
|
||||||
fn test_cbor_map_options() {
|
fn test_cbor_map_options() {
|
||||||
let a = cbor_map_options! {
|
let a = cbor_map_options! {
|
||||||
-1 => -23,
|
|
||||||
4 => Some(56),
|
4 => Some(56),
|
||||||
11 => None::<String>,
|
|
||||||
"foo" => true,
|
|
||||||
12 => None::<&str>,
|
|
||||||
b"bar" => Some(cbor_null!()),
|
|
||||||
13 => None::<Vec<u8>>,
|
|
||||||
5 => "foo",
|
5 => "foo",
|
||||||
14 => None::<&[u8]>,
|
|
||||||
6 => Some(b"bar" as &[u8]),
|
6 => Some(b"bar" as &[u8]),
|
||||||
15 => None::<bool>,
|
|
||||||
7 => cbor_array![],
|
7 => cbor_array![],
|
||||||
16 => None::<i32>,
|
|
||||||
8 => Some(cbor_array![0, 1]),
|
8 => Some(cbor_array![0, 1]),
|
||||||
17 => None::<i64>,
|
|
||||||
9 => cbor_map!{},
|
9 => cbor_map!{},
|
||||||
18 => None::<u64>,
|
|
||||||
10 => Some(cbor_map!{2 => 3}),
|
10 => Some(cbor_map!{2 => 3}),
|
||||||
|
11 => None::<String>,
|
||||||
|
12 => None::<&str>,
|
||||||
|
13 => None::<Vec<u8>>,
|
||||||
|
14 => None::<&[u8]>,
|
||||||
|
15 => None::<bool>,
|
||||||
|
16 => None::<i32>,
|
||||||
|
17 => None::<i64>,
|
||||||
|
18 => None::<u64>,
|
||||||
|
-1 => -23,
|
||||||
|
b"bar" => Some(cbor_null!()),
|
||||||
|
"foo" => true,
|
||||||
};
|
};
|
||||||
let b = Value::Map(
|
let b = Value::map(
|
||||||
[
|
[
|
||||||
(Value::Negative(-1), Value::Negative(-23)),
|
(Value::from(4), Value::from(56)),
|
||||||
(Value::Unsigned(4), Value::Unsigned(56)),
|
(Value::from(5), Value::from(String::from("foo"))),
|
||||||
|
(Value::from(6), Value::from(b"bar".to_vec())),
|
||||||
|
(Value::from(7), Value::array(Vec::new())),
|
||||||
(
|
(
|
||||||
Value::TextString(String::from("foo")),
|
Value::from(8),
|
||||||
Value::Simple(SimpleValue::TrueValue),
|
Value::array(vec![Value::from(0), Value::from(1)]),
|
||||||
),
|
),
|
||||||
|
(Value::from(9), Value::map(Vec::new())),
|
||||||
(
|
(
|
||||||
Value::ByteString(b"bar".to_vec()),
|
Value::from(10),
|
||||||
Value::Simple(SimpleValue::NullValue),
|
Value::map([(Value::from(2), Value::from(3))].iter().cloned().collect()),
|
||||||
),
|
|
||||||
(Value::Unsigned(5), Value::TextString(String::from("foo"))),
|
|
||||||
(Value::Unsigned(6), Value::ByteString(b"bar".to_vec())),
|
|
||||||
(Value::Unsigned(7), Value::Array(Vec::new())),
|
|
||||||
(
|
|
||||||
Value::Unsigned(8),
|
|
||||||
Value::Array(vec![Value::Unsigned(0), Value::Unsigned(1)]),
|
|
||||||
),
|
|
||||||
(Value::Unsigned(9), Value::Map(Vec::new())),
|
|
||||||
(
|
|
||||||
Value::Unsigned(10),
|
|
||||||
Value::Map(
|
|
||||||
[(Value::Unsigned(2), Value::Unsigned(3))]
|
|
||||||
.iter()
|
|
||||||
.cloned()
|
|
||||||
.collect(),
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
|
(Value::from(-1), Value::from(-23)),
|
||||||
|
(Value::from(b"bar".to_vec()), Value::null_value()),
|
||||||
|
(Value::from(String::from("foo")), Value::bool_value(true)),
|
||||||
]
|
]
|
||||||
.iter()
|
.iter()
|
||||||
.cloned()
|
.cloned()
|
||||||
@@ -616,22 +592,19 @@ mod test {
|
|||||||
#[test]
|
#[test]
|
||||||
fn test_cbor_map_collection_empty() {
|
fn test_cbor_map_collection_empty() {
|
||||||
let a = cbor_map_collection!(Vec::<(_, _)>::new());
|
let a = cbor_map_collection!(Vec::<(_, _)>::new());
|
||||||
let b = Value::Map(Vec::new());
|
let b = Value::map(Vec::new());
|
||||||
assert_eq!(a, b);
|
assert_eq!(a, b);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_cbor_map_collection_foo() {
|
fn test_cbor_map_collection_foo() {
|
||||||
let a = cbor_map_collection!(vec![(Value::Unsigned(2), Value::Unsigned(3))]);
|
let a = cbor_map_collection!(vec![(Value::from(2), Value::from(3))]);
|
||||||
let b = Value::Map(vec![(Value::Unsigned(2), Value::Unsigned(3))]);
|
let b = Value::map(vec![(Value::from(2), Value::from(3))]);
|
||||||
assert_eq!(a, b);
|
assert_eq!(a, b);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn extract_map(cbor_value: Value) -> Vec<(Value, Value)> {
|
fn extract_map(cbor_value: Value) -> Vec<(Value, Value)> {
|
||||||
match cbor_value {
|
cbor_value.extract_map().unwrap()
|
||||||
Value::Map(map) => map,
|
|
||||||
_ => panic!("Expected CBOR map."),
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
@@ -721,4 +694,22 @@ mod test {
|
|||||||
assert_eq!(x4, Some(cbor_unsigned!(40)));
|
assert_eq!(x4, Some(cbor_unsigned!(40)));
|
||||||
assert_eq!(x5, None);
|
assert_eq!(x5, None);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_destructure_unsorted_cbor_map() {
|
||||||
|
let map = cbor_map! {
|
||||||
|
2 => 20,
|
||||||
|
1 => 10,
|
||||||
|
};
|
||||||
|
|
||||||
|
destructure_cbor_map! {
|
||||||
|
let {
|
||||||
|
1 => x1,
|
||||||
|
2 => x2,
|
||||||
|
} = extract_map(map);
|
||||||
|
}
|
||||||
|
|
||||||
|
assert_eq!(x1, Some(cbor_unsigned!(10)));
|
||||||
|
assert_eq!(x2, Some(cbor_unsigned!(20)));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -14,7 +14,7 @@
|
|||||||
|
|
||||||
//! Functionality for deserializing CBOR data into values.
|
//! Functionality for deserializing CBOR data into values.
|
||||||
|
|
||||||
use super::values::{Constants, SimpleValue, Value};
|
use super::values::{Constants, SimpleValue, Value, ValueImpl};
|
||||||
use crate::{
|
use crate::{
|
||||||
cbor_array_vec, cbor_bytes_lit, cbor_map_collection, cbor_tagged, cbor_text, cbor_unsigned,
|
cbor_array_vec, cbor_bytes_lit, cbor_map_collection, cbor_tagged, cbor_text, cbor_unsigned,
|
||||||
};
|
};
|
||||||
@@ -144,7 +144,7 @@ impl<'a> Reader<'a> {
|
|||||||
if signed_size < 0 {
|
if signed_size < 0 {
|
||||||
Err(DecoderError::OutOfRangeIntegerValue)
|
Err(DecoderError::OutOfRangeIntegerValue)
|
||||||
} else {
|
} else {
|
||||||
Ok(Value::Negative(-(size_value as i64) - 1))
|
Ok(Value(ValueImpl::Negative(-(size_value as i64) - 1)))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -221,7 +221,7 @@ impl<'a> Reader<'a> {
|
|||||||
return Err(DecoderError::UnsupportedFloatingPointValue);
|
return Err(DecoderError::UnsupportedFloatingPointValue);
|
||||||
}
|
}
|
||||||
match SimpleValue::from_integer(size_value) {
|
match SimpleValue::from_integer(size_value) {
|
||||||
Some(simple_value) => Ok(Value::Simple(simple_value)),
|
Some(simple_value) => Ok(Value(ValueImpl::Simple(simple_value))),
|
||||||
None => Err(DecoderError::UnsupportedSimpleValue),
|
None => Err(DecoderError::UnsupportedSimpleValue),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -19,9 +19,13 @@ use alloc::string::{String, ToString};
|
|||||||
use alloc::vec::Vec;
|
use alloc::vec::Vec;
|
||||||
use core::cmp::Ordering;
|
use core::cmp::Ordering;
|
||||||
|
|
||||||
|
/// The CBOR data structure.
|
||||||
|
#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord)]
|
||||||
|
pub struct Value(pub(crate) ValueImpl);
|
||||||
|
|
||||||
/// Possible CBOR values.
|
/// Possible CBOR values.
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug)]
|
||||||
pub enum Value {
|
pub(crate) enum ValueImpl {
|
||||||
/// Unsigned integer value (uint).
|
/// Unsigned integer value (uint).
|
||||||
Unsigned(u64),
|
Unsigned(u64),
|
||||||
/// Signed integer value (nint). Only 63 bits of information are used here.
|
/// Signed integer value (nint). Only 63 bits of information are used here.
|
||||||
@@ -42,7 +46,7 @@ pub enum Value {
|
|||||||
|
|
||||||
/// Specific simple CBOR values.
|
/// Specific simple CBOR values.
|
||||||
#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord)]
|
#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord)]
|
||||||
pub enum SimpleValue {
|
pub(crate) enum SimpleValue {
|
||||||
FalseValue = 20,
|
FalseValue = 20,
|
||||||
TrueValue = 21,
|
TrueValue = 21,
|
||||||
NullValue = 22,
|
NullValue = 22,
|
||||||
@@ -71,45 +75,177 @@ impl Constants {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl Value {
|
impl Value {
|
||||||
|
/// Creates a CBOR unsigned value.
|
||||||
|
pub fn unsigned(int: u64) -> Value {
|
||||||
|
Value(ValueImpl::Unsigned(int))
|
||||||
|
}
|
||||||
|
|
||||||
/// Create an appropriate CBOR integer value (uint/nint).
|
/// Create an appropriate CBOR integer value (uint/nint).
|
||||||
/// For simplicity, this only takes i64. Construct directly for the last bit.
|
/// For simplicity, this only takes i64. Construct directly for the last bit.
|
||||||
pub fn integer(int: i64) -> Value {
|
pub fn integer(int: i64) -> Value {
|
||||||
if int >= 0 {
|
if int >= 0 {
|
||||||
Value::Unsigned(int as u64)
|
Value(ValueImpl::Unsigned(int as u64))
|
||||||
} else {
|
} else {
|
||||||
Value::Negative(int)
|
Value(ValueImpl::Negative(int))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Creates a CBOR byte string value.
|
||||||
|
pub fn byte_string(bytes: Vec<u8>) -> Value {
|
||||||
|
Value(ValueImpl::ByteString(bytes))
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Creates a CBOR text string value.
|
||||||
|
pub fn text_string(text: String) -> Value {
|
||||||
|
Value(ValueImpl::TextString(text))
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Create a CBOR array value.
|
||||||
|
pub fn array(a: Vec<Value>) -> Value {
|
||||||
|
Value(ValueImpl::Array(a))
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Create a CBOR map value.
|
||||||
|
///
|
||||||
|
/// Keys do not have to be sorted.
|
||||||
|
///
|
||||||
|
/// # Panics
|
||||||
|
///
|
||||||
|
/// You may not call this function with identical keys in its argument.
|
||||||
|
pub fn map(mut m: Vec<(Value, Value)>) -> Value {
|
||||||
|
m.sort_by(|a, b| a.0.cmp(&b.0));
|
||||||
|
let map_len = m.len();
|
||||||
|
m.dedup_by(|a, b| a.0.eq(&b.0));
|
||||||
|
if map_len != m.len() {
|
||||||
|
panic!();
|
||||||
|
}
|
||||||
|
Value(ValueImpl::Map(m))
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Create a CBOR tagged value.
|
||||||
|
pub fn tag(int: u64, value: Value) -> Value {
|
||||||
|
Value(ValueImpl::Tag(int, Box::new(value)))
|
||||||
|
}
|
||||||
|
|
||||||
/// Create a CBOR boolean simple value.
|
/// Create a CBOR boolean simple value.
|
||||||
pub fn bool_value(b: bool) -> Value {
|
pub fn bool_value(b: bool) -> Value {
|
||||||
if b {
|
if b {
|
||||||
Value::Simple(SimpleValue::TrueValue)
|
Value(ValueImpl::Simple(SimpleValue::TrueValue))
|
||||||
} else {
|
} else {
|
||||||
Value::Simple(SimpleValue::FalseValue)
|
Value(ValueImpl::Simple(SimpleValue::FalseValue))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Return the major type for the [`Value`].
|
/// Creates a null value.
|
||||||
|
pub fn null_value() -> Value {
|
||||||
|
Value(ValueImpl::Simple(SimpleValue::NullValue))
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Creates an undefined value.
|
||||||
|
pub fn undefined() -> Value {
|
||||||
|
Value(ValueImpl::Simple(SimpleValue::Undefined))
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn extract_unsigned(self) -> Option<u64> {
|
||||||
|
match self {
|
||||||
|
Value(ValueImpl::Unsigned(unsigned)) => Some(unsigned),
|
||||||
|
_ => None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn extract_integer(self) -> Option<i64> {
|
||||||
|
match self {
|
||||||
|
Value(ValueImpl::Unsigned(unsigned)) => {
|
||||||
|
if unsigned <= core::i64::MAX as u64 {
|
||||||
|
Some(unsigned as i64)
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Value(ValueImpl::Negative(signed)) => Some(signed),
|
||||||
|
_ => None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn extract_byte_string(self) -> Option<Vec<u8>> {
|
||||||
|
match self {
|
||||||
|
Value(ValueImpl::ByteString(byte_string)) => Some(byte_string),
|
||||||
|
_ => None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn extract_text_string(self) -> Option<String> {
|
||||||
|
match self {
|
||||||
|
Value(ValueImpl::TextString(text_string)) => Some(text_string),
|
||||||
|
_ => None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn extract_array(self) -> Option<Vec<Value>> {
|
||||||
|
match self {
|
||||||
|
Value(ValueImpl::Array(array)) => Some(array),
|
||||||
|
_ => None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn extract_map(self) -> Option<Vec<(Value, Value)>> {
|
||||||
|
match self {
|
||||||
|
Value(ValueImpl::Map(map)) => Some(map),
|
||||||
|
_ => None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn extract_tag(self) -> Option<(u64, Value)> {
|
||||||
|
match self {
|
||||||
|
Value(ValueImpl::Tag(tag, value)) => Some((tag, *value)),
|
||||||
|
_ => None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn extract_bool(self) -> Option<bool> {
|
||||||
|
match self {
|
||||||
|
Value(ValueImpl::Simple(SimpleValue::FalseValue)) => Some(false),
|
||||||
|
Value(ValueImpl::Simple(SimpleValue::TrueValue)) => Some(true),
|
||||||
|
_ => None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn extract_null(self) -> Option<()> {
|
||||||
|
match self {
|
||||||
|
Value(ValueImpl::Simple(SimpleValue::NullValue)) => Some(()),
|
||||||
|
_ => None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn extract_undefined(self) -> Option<()> {
|
||||||
|
match self {
|
||||||
|
Value(ValueImpl::Simple(SimpleValue::Undefined)) => Some(()),
|
||||||
|
_ => None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ValueImpl {
|
||||||
|
/// Return the major type for the [`ValueImpl`].
|
||||||
pub fn type_label(&self) -> u8 {
|
pub fn type_label(&self) -> u8 {
|
||||||
// TODO use enum discriminant instead when stable
|
// TODO use enum discriminant instead when stable
|
||||||
// https://github.com/rust-lang/rust/issues/60553
|
// https://github.com/rust-lang/rust/issues/60553
|
||||||
match self {
|
match self {
|
||||||
Value::Unsigned(_) => 0,
|
ValueImpl::Unsigned(_) => 0,
|
||||||
Value::Negative(_) => 1,
|
ValueImpl::Negative(_) => 1,
|
||||||
Value::ByteString(_) => 2,
|
ValueImpl::ByteString(_) => 2,
|
||||||
Value::TextString(_) => 3,
|
ValueImpl::TextString(_) => 3,
|
||||||
Value::Array(_) => 4,
|
ValueImpl::Array(_) => 4,
|
||||||
Value::Map(_) => 5,
|
ValueImpl::Map(_) => 5,
|
||||||
Value::Tag(_, _) => 6,
|
ValueImpl::Tag(_, _) => 6,
|
||||||
Value::Simple(_) => 7,
|
ValueImpl::Simple(_) => 7,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Ord for Value {
|
impl Ord for ValueImpl {
|
||||||
fn cmp(&self, other: &Value) -> Ordering {
|
fn cmp(&self, other: &ValueImpl) -> Ordering {
|
||||||
use super::values::Value::{
|
use super::values::ValueImpl::{
|
||||||
Array, ByteString, Map, Negative, Simple, Tag, TextString, Unsigned,
|
Array, ByteString, Map, Negative, Simple, Tag, TextString, Unsigned,
|
||||||
};
|
};
|
||||||
let self_type_value = self.type_label();
|
let self_type_value = self.type_label();
|
||||||
@@ -156,16 +292,16 @@ impl Ord for Value {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl PartialOrd for Value {
|
impl PartialOrd for ValueImpl {
|
||||||
fn partial_cmp(&self, other: &Value) -> Option<Ordering> {
|
fn partial_cmp(&self, other: &ValueImpl) -> Option<Ordering> {
|
||||||
Some(self.cmp(other))
|
Some(self.cmp(other))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Eq for Value {}
|
impl Eq for ValueImpl {}
|
||||||
|
|
||||||
impl PartialEq for Value {
|
impl PartialEq for ValueImpl {
|
||||||
fn eq(&self, other: &Value) -> bool {
|
fn eq(&self, other: &ValueImpl) -> bool {
|
||||||
self.cmp(other) == Ordering::Equal
|
self.cmp(other) == Ordering::Equal
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -184,8 +320,26 @@ impl SimpleValue {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl From<u64> for Value {
|
impl From<u64> for Value {
|
||||||
fn from(unsigned: u64) -> Self {
|
fn from(u: u64) -> Self {
|
||||||
Value::Unsigned(unsigned)
|
Value::unsigned(u)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<u32> for Value {
|
||||||
|
fn from(u: u32) -> Self {
|
||||||
|
Value::unsigned(u as u64)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<u16> for Value {
|
||||||
|
fn from(u: u16) -> Self {
|
||||||
|
Value::unsigned(u as u64)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<u8> for Value {
|
||||||
|
fn from(u: u8) -> Self {
|
||||||
|
Value::unsigned(u as u64)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -201,39 +355,57 @@ impl From<i32> for Value {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl From<i16> for Value {
|
||||||
|
fn from(i: i16) -> Self {
|
||||||
|
Value::integer(i as i64)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<i8> for Value {
|
||||||
|
fn from(i: i8) -> Self {
|
||||||
|
Value::integer(i as i64)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl From<Vec<u8>> for Value {
|
impl From<Vec<u8>> for Value {
|
||||||
fn from(bytes: Vec<u8>) -> Self {
|
fn from(bytes: Vec<u8>) -> Self {
|
||||||
Value::ByteString(bytes)
|
Value(ValueImpl::ByteString(bytes))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<&[u8]> for Value {
|
impl From<&[u8]> for Value {
|
||||||
fn from(bytes: &[u8]) -> Self {
|
fn from(bytes: &[u8]) -> Self {
|
||||||
Value::ByteString(bytes.to_vec())
|
Value(ValueImpl::ByteString(bytes.to_vec()))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<&[u8; 0]> for Value {
|
||||||
|
fn from(bytes: &[u8; 0]) -> Self {
|
||||||
|
Value(ValueImpl::ByteString(bytes.to_vec()))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<String> for Value {
|
impl From<String> for Value {
|
||||||
fn from(text: String) -> Self {
|
fn from(text: String) -> Self {
|
||||||
Value::TextString(text)
|
Value(ValueImpl::TextString(text))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<&str> for Value {
|
impl From<&str> for Value {
|
||||||
fn from(text: &str) -> Self {
|
fn from(text: &str) -> Self {
|
||||||
Value::TextString(text.to_string())
|
Value(ValueImpl::TextString(text.to_string()))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<Vec<Value>> for Value {
|
impl From<Vec<Value>> for Value {
|
||||||
fn from(array: Vec<Value>) -> Self {
|
fn from(array: Vec<Value>) -> Self {
|
||||||
Value::Array(array)
|
Value(ValueImpl::Array(array))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<Vec<(Value, Value)>> for Value {
|
impl From<Vec<(Value, Value)>> for Value {
|
||||||
fn from(map: Vec<(Value, Value)>) -> Self {
|
fn from(map: Vec<(Value, Value)>) -> Self {
|
||||||
Value::Map(map)
|
Value::map(map)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -285,9 +457,209 @@ where
|
|||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod test {
|
mod test {
|
||||||
use super::*;
|
use super::*;
|
||||||
use crate::{cbor_array, cbor_bool, cbor_bytes, cbor_int, cbor_map, cbor_tagged, cbor_text};
|
use crate::{
|
||||||
|
cbor_array, cbor_bool, cbor_bytes, cbor_bytes_lit, cbor_int, cbor_map, cbor_null,
|
||||||
|
cbor_tagged, cbor_text, cbor_undefined, cbor_unsigned,
|
||||||
|
};
|
||||||
use alloc::vec;
|
use alloc::vec;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
#[should_panic]
|
||||||
|
fn test_duplicate_map_key() {
|
||||||
|
let _map = cbor_map! {
|
||||||
|
0 => "a",
|
||||||
|
-1 => "c",
|
||||||
|
b"a" => "e",
|
||||||
|
"c" => "g",
|
||||||
|
0 => "b",
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_extract_unsigned() {
|
||||||
|
assert_eq!(cbor_int!(1).extract_unsigned(), Some(1));
|
||||||
|
assert_eq!(cbor_int!(-1).extract_unsigned(), None);
|
||||||
|
assert_eq!(cbor_bytes!(vec![]).extract_unsigned(), None);
|
||||||
|
assert_eq!(cbor_text!("").extract_unsigned(), None);
|
||||||
|
assert_eq!(cbor_array![].extract_unsigned(), None);
|
||||||
|
assert_eq!(cbor_map! {}.extract_unsigned(), None);
|
||||||
|
assert_eq!(cbor_tagged!(1, cbor_text!("s")).extract_unsigned(), None);
|
||||||
|
assert_eq!(cbor_bool!(false).extract_unsigned(), None);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_extract_unsigned_limits() {
|
||||||
|
assert_eq!(
|
||||||
|
cbor_unsigned!(core::u64::MAX).extract_unsigned(),
|
||||||
|
Some(core::u64::MAX)
|
||||||
|
);
|
||||||
|
assert_eq!(
|
||||||
|
cbor_unsigned!((core::i64::MAX as u64) + 1).extract_unsigned(),
|
||||||
|
Some((core::i64::MAX as u64) + 1)
|
||||||
|
);
|
||||||
|
assert_eq!(
|
||||||
|
cbor_int!(core::i64::MAX).extract_unsigned(),
|
||||||
|
Some(core::i64::MAX as u64)
|
||||||
|
);
|
||||||
|
assert_eq!(cbor_int!(123).extract_unsigned(), Some(123));
|
||||||
|
assert_eq!(cbor_int!(0).extract_unsigned(), Some(0));
|
||||||
|
assert_eq!(cbor_int!(-123).extract_unsigned(), None);
|
||||||
|
assert_eq!(cbor_int!(core::i64::MIN).extract_unsigned(), None);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_extract_integer() {
|
||||||
|
assert_eq!(cbor_int!(1).extract_integer(), Some(1));
|
||||||
|
assert_eq!(cbor_int!(-1).extract_integer(), Some(-1));
|
||||||
|
assert_eq!(cbor_bytes!(vec![]).extract_integer(), None);
|
||||||
|
assert_eq!(cbor_text!("").extract_integer(), None);
|
||||||
|
assert_eq!(cbor_array![].extract_integer(), None);
|
||||||
|
assert_eq!(cbor_map! {}.extract_integer(), None);
|
||||||
|
assert_eq!(cbor_tagged!(1, cbor_text!("s")).extract_integer(), None);
|
||||||
|
assert_eq!(cbor_bool!(false).extract_integer(), None);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_extract_integer_limits() {
|
||||||
|
assert_eq!(cbor_unsigned!(core::u64::MAX).extract_integer(), None);
|
||||||
|
assert_eq!(
|
||||||
|
cbor_unsigned!((core::i64::MAX as u64) + 1).extract_integer(),
|
||||||
|
None
|
||||||
|
);
|
||||||
|
assert_eq!(
|
||||||
|
cbor_int!(core::i64::MAX).extract_integer(),
|
||||||
|
Some(core::i64::MAX)
|
||||||
|
);
|
||||||
|
assert_eq!(cbor_int!(123).extract_integer(), Some(123));
|
||||||
|
assert_eq!(cbor_int!(0).extract_integer(), Some(0));
|
||||||
|
assert_eq!(cbor_int!(-123).extract_integer(), Some(-123));
|
||||||
|
assert_eq!(
|
||||||
|
cbor_int!(core::i64::MIN).extract_integer(),
|
||||||
|
Some(core::i64::MIN)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_extract_byte_string() {
|
||||||
|
assert_eq!(cbor_int!(1).extract_byte_string(), None);
|
||||||
|
assert_eq!(cbor_int!(-1).extract_byte_string(), None);
|
||||||
|
assert_eq!(cbor_bytes!(vec![]).extract_byte_string(), Some(Vec::new()));
|
||||||
|
assert_eq!(
|
||||||
|
cbor_bytes_lit!(b"bar").extract_byte_string(),
|
||||||
|
Some(b"bar".to_vec())
|
||||||
|
);
|
||||||
|
assert_eq!(cbor_text!("").extract_byte_string(), None);
|
||||||
|
assert_eq!(cbor_array![].extract_byte_string(), None);
|
||||||
|
assert_eq!(cbor_map! {}.extract_byte_string(), None);
|
||||||
|
assert_eq!(cbor_tagged!(1, cbor_text!("s")).extract_byte_string(), None);
|
||||||
|
assert_eq!(cbor_bool!(false).extract_byte_string(), None);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_extract_text_string() {
|
||||||
|
assert_eq!(cbor_int!(1).extract_text_string(), None);
|
||||||
|
assert_eq!(cbor_int!(-1).extract_text_string(), None);
|
||||||
|
assert_eq!(cbor_bytes!(vec![]).extract_text_string(), None);
|
||||||
|
assert_eq!(cbor_text!("").extract_text_string(), Some(String::new()));
|
||||||
|
assert_eq!(cbor_text!("s").extract_text_string(), Some("s".to_string()));
|
||||||
|
assert_eq!(cbor_array![].extract_text_string(), None);
|
||||||
|
assert_eq!(cbor_map! {}.extract_text_string(), None);
|
||||||
|
assert_eq!(cbor_tagged!(1, cbor_text!("s")).extract_text_string(), None);
|
||||||
|
assert_eq!(cbor_bool!(false).extract_text_string(), None);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_extract_array() {
|
||||||
|
assert_eq!(cbor_int!(1).extract_array(), None);
|
||||||
|
assert_eq!(cbor_int!(-1).extract_array(), None);
|
||||||
|
assert_eq!(cbor_bytes!(vec![]).extract_array(), None);
|
||||||
|
assert_eq!(cbor_text!("").extract_array(), None);
|
||||||
|
assert_eq!(cbor_array![].extract_array(), Some(Vec::new()));
|
||||||
|
assert_eq!(
|
||||||
|
cbor_array![cbor_int!(1)].extract_array(),
|
||||||
|
Some(vec![cbor_int!(1)])
|
||||||
|
);
|
||||||
|
assert_eq!(cbor_map! {}.extract_array(), None);
|
||||||
|
assert_eq!(cbor_tagged!(1, cbor_text!("s")).extract_array(), None);
|
||||||
|
assert_eq!(cbor_bool!(false).extract_array(), None);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_extract_map() {
|
||||||
|
assert_eq!(cbor_int!(1).extract_map(), None);
|
||||||
|
assert_eq!(cbor_int!(-1).extract_map(), None);
|
||||||
|
assert_eq!(cbor_bytes!(vec![]).extract_map(), None);
|
||||||
|
assert_eq!(cbor_text!("").extract_map(), None);
|
||||||
|
assert_eq!(cbor_array![].extract_map(), None);
|
||||||
|
assert_eq!(cbor_map! {}.extract_map(), Some(Vec::new()));
|
||||||
|
assert_eq!(
|
||||||
|
cbor_map! {0 => 1}.extract_map(),
|
||||||
|
Some(vec![(cbor_int!(0), cbor_int!(1))])
|
||||||
|
);
|
||||||
|
assert_eq!(cbor_tagged!(1, cbor_text!("s")).extract_map(), None);
|
||||||
|
assert_eq!(cbor_bool!(false).extract_map(), None);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_extract_tag() {
|
||||||
|
assert_eq!(cbor_int!(1).extract_tag(), None);
|
||||||
|
assert_eq!(cbor_int!(-1).extract_tag(), None);
|
||||||
|
assert_eq!(cbor_bytes!(vec![]).extract_tag(), None);
|
||||||
|
assert_eq!(cbor_text!("").extract_tag(), None);
|
||||||
|
assert_eq!(cbor_array![].extract_tag(), None);
|
||||||
|
assert_eq!(cbor_map! {}.extract_tag(), None);
|
||||||
|
assert_eq!(
|
||||||
|
cbor_tagged!(1, cbor_text!("s")).extract_tag(),
|
||||||
|
Some((1, cbor_text!("s")))
|
||||||
|
);
|
||||||
|
assert_eq!(cbor_bool!(false).extract_tag(), None);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_extract_bool() {
|
||||||
|
assert_eq!(cbor_int!(1).extract_bool(), None);
|
||||||
|
assert_eq!(cbor_int!(-1).extract_bool(), None);
|
||||||
|
assert_eq!(cbor_bytes!(vec![]).extract_bool(), None);
|
||||||
|
assert_eq!(cbor_text!("").extract_bool(), None);
|
||||||
|
assert_eq!(cbor_array![].extract_bool(), None);
|
||||||
|
assert_eq!(cbor_map! {}.extract_bool(), None);
|
||||||
|
assert_eq!(cbor_tagged!(1, cbor_text!("s")).extract_bool(), None);
|
||||||
|
assert_eq!(cbor_bool!(false).extract_bool(), Some(false));
|
||||||
|
assert_eq!(cbor_bool!(true).extract_bool(), Some(true));
|
||||||
|
assert_eq!(cbor_null!().extract_bool(), None);
|
||||||
|
assert_eq!(cbor_undefined!().extract_bool(), None);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_extract_null() {
|
||||||
|
assert_eq!(cbor_int!(1).extract_null(), None);
|
||||||
|
assert_eq!(cbor_int!(-1).extract_null(), None);
|
||||||
|
assert_eq!(cbor_bytes!(vec![]).extract_null(), None);
|
||||||
|
assert_eq!(cbor_text!("").extract_null(), None);
|
||||||
|
assert_eq!(cbor_array![].extract_null(), None);
|
||||||
|
assert_eq!(cbor_map! {}.extract_null(), None);
|
||||||
|
assert_eq!(cbor_tagged!(1, cbor_text!("s")).extract_null(), None);
|
||||||
|
assert_eq!(cbor_bool!(false).extract_null(), None);
|
||||||
|
assert_eq!(cbor_bool!(true).extract_null(), None);
|
||||||
|
assert_eq!(cbor_null!().extract_null(), Some(()));
|
||||||
|
assert_eq!(cbor_undefined!().extract_null(), None);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_extract_undefined() {
|
||||||
|
assert_eq!(cbor_int!(1).extract_undefined(), None);
|
||||||
|
assert_eq!(cbor_int!(-1).extract_undefined(), None);
|
||||||
|
assert_eq!(cbor_bytes!(vec![]).extract_undefined(), None);
|
||||||
|
assert_eq!(cbor_text!("").extract_undefined(), None);
|
||||||
|
assert_eq!(cbor_array![].extract_undefined(), None);
|
||||||
|
assert_eq!(cbor_map! {}.extract_undefined(), None);
|
||||||
|
assert_eq!(cbor_tagged!(1, cbor_text!("s")).extract_undefined(), None);
|
||||||
|
assert_eq!(cbor_bool!(false).extract_undefined(), None);
|
||||||
|
assert_eq!(cbor_bool!(true).extract_undefined(), None);
|
||||||
|
assert_eq!(cbor_null!().extract_undefined(), None);
|
||||||
|
assert_eq!(cbor_undefined!().extract_undefined(), Some(()));
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_value_ordering() {
|
fn test_value_ordering() {
|
||||||
assert!(cbor_int!(0) < cbor_int!(23));
|
assert!(cbor_int!(0) < cbor_int!(23));
|
||||||
@@ -329,12 +701,12 @@ mod test {
|
|||||||
assert!(cbor_map! {"" => 0} < cbor_map! {cbor_array![] => 0});
|
assert!(cbor_map! {"" => 0} < cbor_map! {cbor_array![] => 0});
|
||||||
assert!(cbor_map! {cbor_array![] => 0} < cbor_map! {cbor_map!{} => 0});
|
assert!(cbor_map! {cbor_array![] => 0} < cbor_map! {cbor_map!{} => 0});
|
||||||
assert!(cbor_map! {cbor_map!{} => 0} < cbor_map! {false => 0});
|
assert!(cbor_map! {cbor_map!{} => 0} < cbor_map! {false => 0});
|
||||||
assert!(cbor_map! {false => 0} < cbor_map! {0 => 0, 0 => 0});
|
assert!(cbor_map! {false => 0} < cbor_map! {0 => 0, 1 => 0});
|
||||||
assert!(cbor_map! {0 => 0} < cbor_tagged!(2, cbor_int!(0)));
|
assert!(cbor_map! {0 => 0} < cbor_tagged!(2, cbor_int!(0)));
|
||||||
assert!(cbor_map! {0 => 0, 0 => 0} < cbor_bool!(false));
|
assert!(cbor_map! {0 => 0, 1 => 0} < cbor_bool!(false));
|
||||||
assert!(cbor_bool!(false) < cbor_bool!(true));
|
assert!(cbor_bool!(false) < cbor_bool!(true));
|
||||||
assert!(cbor_bool!(true) < Value::Simple(SimpleValue::NullValue));
|
assert!(cbor_bool!(true) < cbor_null!());
|
||||||
assert!(Value::Simple(SimpleValue::NullValue) < Value::Simple(SimpleValue::Undefined));
|
assert!(cbor_null!() < cbor_undefined!());
|
||||||
assert!(cbor_tagged!(1, cbor_text!("s")) < cbor_tagged!(2, cbor_int!(0)));
|
assert!(cbor_tagged!(1, cbor_text!("s")) < cbor_tagged!(2, cbor_int!(0)));
|
||||||
assert!(cbor_int!(1) < cbor_int!(-1));
|
assert!(cbor_int!(1) < cbor_int!(-1));
|
||||||
assert!(cbor_int!(1) < cbor_bytes!(vec![0x00]));
|
assert!(cbor_int!(1) < cbor_bytes!(vec![0x00]));
|
||||||
|
|||||||
@@ -14,7 +14,7 @@
|
|||||||
|
|
||||||
//! Functionality for serializing CBOR values into bytes.
|
//! Functionality for serializing CBOR values into bytes.
|
||||||
|
|
||||||
use super::values::{Constants, Value};
|
use super::values::{Constants, Value, ValueImpl};
|
||||||
use alloc::vec::Vec;
|
use alloc::vec::Vec;
|
||||||
|
|
||||||
/// Possible errors from a serialization operation.
|
/// Possible errors from a serialization operation.
|
||||||
@@ -60,42 +60,36 @@ impl<'a> Writer<'a> {
|
|||||||
if remaining_depth.map_or(false, |d| d < 0) {
|
if remaining_depth.map_or(false, |d| d < 0) {
|
||||||
return Err(EncoderError::TooMuchNesting);
|
return Err(EncoderError::TooMuchNesting);
|
||||||
}
|
}
|
||||||
let type_label = value.type_label();
|
let type_label = value.0.type_label();
|
||||||
match value {
|
match value.0 {
|
||||||
Value::Unsigned(unsigned) => self.start_item(type_label, unsigned),
|
ValueImpl::Unsigned(unsigned) => self.start_item(type_label, unsigned),
|
||||||
Value::Negative(negative) => self.start_item(type_label, -(negative + 1) as u64),
|
ValueImpl::Negative(negative) => self.start_item(type_label, -(negative + 1) as u64),
|
||||||
Value::ByteString(byte_string) => {
|
ValueImpl::ByteString(byte_string) => {
|
||||||
self.start_item(type_label, byte_string.len() as u64);
|
self.start_item(type_label, byte_string.len() as u64);
|
||||||
self.encoded_cbor.extend(byte_string);
|
self.encoded_cbor.extend(byte_string);
|
||||||
}
|
}
|
||||||
Value::TextString(text_string) => {
|
ValueImpl::TextString(text_string) => {
|
||||||
self.start_item(type_label, text_string.len() as u64);
|
self.start_item(type_label, text_string.len() as u64);
|
||||||
self.encoded_cbor.extend(text_string.into_bytes());
|
self.encoded_cbor.extend(text_string.into_bytes());
|
||||||
}
|
}
|
||||||
Value::Array(array) => {
|
ValueImpl::Array(array) => {
|
||||||
self.start_item(type_label, array.len() as u64);
|
self.start_item(type_label, array.len() as u64);
|
||||||
for el in array {
|
for el in array {
|
||||||
self.encode_cbor(el, remaining_depth.map(|d| d - 1))?;
|
self.encode_cbor(el, remaining_depth.map(|d| d - 1))?;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Value::Map(mut map) => {
|
ValueImpl::Map(map) => {
|
||||||
map.sort_by(|a, b| a.0.cmp(&b.0));
|
self.start_item(type_label, map.len() as u64);
|
||||||
let map_len = map.len();
|
|
||||||
map.dedup_by(|a, b| a.0.eq(&b.0));
|
|
||||||
if map_len != map.len() {
|
|
||||||
return Err(EncoderError::DuplicateMapKey);
|
|
||||||
}
|
|
||||||
self.start_item(type_label, map_len as u64);
|
|
||||||
for (k, v) in map {
|
for (k, v) in map {
|
||||||
self.encode_cbor(k, remaining_depth.map(|d| d - 1))?;
|
self.encode_cbor(k, remaining_depth.map(|d| d - 1))?;
|
||||||
self.encode_cbor(v, remaining_depth.map(|d| d - 1))?;
|
self.encode_cbor(v, remaining_depth.map(|d| d - 1))?;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Value::Tag(tag, inner_value) => {
|
ValueImpl::Tag(tag, inner_value) => {
|
||||||
self.start_item(type_label, tag);
|
self.start_item(type_label, tag);
|
||||||
self.encode_cbor(*inner_value, remaining_depth.map(|d| d - 1))?;
|
self.encode_cbor(*inner_value, remaining_depth.map(|d| d - 1))?;
|
||||||
}
|
}
|
||||||
Value::Simple(simple_value) => self.start_item(type_label, simple_value as u64),
|
ValueImpl::Simple(simple_value) => self.start_item(type_label, simple_value as u64),
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
@@ -342,42 +336,6 @@ mod test {
|
|||||||
assert_eq!(write_return(sorted_map), write_return(unsorted_map));
|
assert_eq!(write_return(sorted_map), write_return(unsorted_map));
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn test_write_map_duplicates() {
|
|
||||||
let duplicate0 = cbor_map! {
|
|
||||||
0 => "a",
|
|
||||||
-1 => "c",
|
|
||||||
b"a" => "e",
|
|
||||||
"c" => "g",
|
|
||||||
0 => "b",
|
|
||||||
};
|
|
||||||
assert_eq!(write_return(duplicate0), None);
|
|
||||||
let duplicate1 = cbor_map! {
|
|
||||||
0 => "a",
|
|
||||||
-1 => "c",
|
|
||||||
b"a" => "e",
|
|
||||||
"c" => "g",
|
|
||||||
-1 => "d",
|
|
||||||
};
|
|
||||||
assert_eq!(write_return(duplicate1), None);
|
|
||||||
let duplicate2 = cbor_map! {
|
|
||||||
0 => "a",
|
|
||||||
-1 => "c",
|
|
||||||
b"a" => "e",
|
|
||||||
"c" => "g",
|
|
||||||
b"a" => "f",
|
|
||||||
};
|
|
||||||
assert_eq!(write_return(duplicate2), None);
|
|
||||||
let duplicate3 = cbor_map! {
|
|
||||||
0 => "a",
|
|
||||||
-1 => "c",
|
|
||||||
b"a" => "e",
|
|
||||||
"c" => "g",
|
|
||||||
"c" => "h",
|
|
||||||
};
|
|
||||||
assert_eq!(write_return(duplicate3), None);
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_write_map_with_array() {
|
fn test_write_map_with_array() {
|
||||||
let value_map = cbor_map! {
|
let value_map = cbor_map! {
|
||||||
|
|||||||
503
libraries/crypto/Cargo.lock
generated
503
libraries/crypto/Cargo.lock
generated
@@ -1,503 +0,0 @@
|
|||||||
# This file is automatically @generated by Cargo.
|
|
||||||
# It is not intended for manual editing.
|
|
||||||
version = 3
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "aho-corasick"
|
|
||||||
version = "0.7.19"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "b4f55bd91a0978cbfd91c457a164bab8b4001c833b7f323132c0a4e1922dd44e"
|
|
||||||
dependencies = [
|
|
||||||
"memchr",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "arrayref"
|
|
||||||
version = "0.3.6"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "a4c527152e37cf757a3f78aae5a06fbeefdb07ccc535c980a3208ee3060dd544"
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "autocfg"
|
|
||||||
version = "0.1.8"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "0dde43e75fd43e8a1bf86103336bc699aa8d17ad1be60c76c0bdfd4828e19b78"
|
|
||||||
dependencies = [
|
|
||||||
"autocfg 1.1.0",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "autocfg"
|
|
||||||
version = "1.1.0"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa"
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "bitflags"
|
|
||||||
version = "1.3.2"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "bumpalo"
|
|
||||||
version = "3.8.0"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "8f1e260c3a9040a7c19a12468758f4c16f31a81a1fe087482be9570ec864bb6c"
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "byteorder"
|
|
||||||
version = "1.4.3"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "14c189c53d098945499cdfa7ecc63567cf3886b3332b312a5b4585d8d3a6a610"
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "cc"
|
|
||||||
version = "1.0.73"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "2fff2a6927b3bb87f9595d67196a70493f627687a71d87a0d692242c33f58c11"
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "cfg-if"
|
|
||||||
version = "1.0.0"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "cloudabi"
|
|
||||||
version = "0.0.3"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "ddfc5b9aa5d4507acaf872de71051dfd0e309860e88966e1051e462a077aac4f"
|
|
||||||
dependencies = [
|
|
||||||
"bitflags",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "crypto"
|
|
||||||
version = "0.1.0"
|
|
||||||
dependencies = [
|
|
||||||
"arrayref",
|
|
||||||
"byteorder",
|
|
||||||
"hex",
|
|
||||||
"regex",
|
|
||||||
"ring",
|
|
||||||
"rng256",
|
|
||||||
"serde",
|
|
||||||
"serde_json",
|
|
||||||
"subtle",
|
|
||||||
"untrusted",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "fuchsia-cprng"
|
|
||||||
version = "0.1.1"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "a06f77d526c1a601b7c4cdd98f54b5eaabffc14d5f2f0296febdc7f357c6d3ba"
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "hex"
|
|
||||||
version = "0.3.2"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "805026a5d0141ffc30abb3be3173848ad46a1b1664fe632428479619a3644d77"
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "itoa"
|
|
||||||
version = "0.4.8"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "b71991ff56294aa922b450139ee08b3bfc70982c6b2c7562771375cf73542dd4"
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "js-sys"
|
|
||||||
version = "0.3.57"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "671a26f820db17c2a2750743f1dd03bafd15b98c9f30c7c2628c024c05d73397"
|
|
||||||
dependencies = [
|
|
||||||
"wasm-bindgen",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "lazy_static"
|
|
||||||
version = "1.4.0"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "libc"
|
|
||||||
version = "0.2.133"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "c0f80d65747a3e43d1596c7c5492d95d5edddaabd45a7fcdb02b95f644164966"
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "libtock_codegen"
|
|
||||||
version = "0.1.0"
|
|
||||||
dependencies = [
|
|
||||||
"proc-macro2",
|
|
||||||
"quote",
|
|
||||||
"syn",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "libtock_core"
|
|
||||||
version = "0.1.0"
|
|
||||||
dependencies = [
|
|
||||||
"libtock_codegen",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "libtock_drivers"
|
|
||||||
version = "0.1.0"
|
|
||||||
dependencies = [
|
|
||||||
"libtock_core",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "log"
|
|
||||||
version = "0.4.17"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "abb12e687cfb44aa40f41fc3978ef76448f9b6038cad6aef4259d3c095a2382e"
|
|
||||||
dependencies = [
|
|
||||||
"cfg-if",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "memchr"
|
|
||||||
version = "2.5.0"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d"
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "once_cell"
|
|
||||||
version = "1.14.0"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "2f7254b99e31cad77da24b08ebf628882739a608578bb1bcdfc1f9c21260d7c0"
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "proc-macro2"
|
|
||||||
version = "1.0.43"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "0a2ca2c61bc9f3d74d2886294ab7b9853abd9c1ad903a3ac7815c58989bb7bab"
|
|
||||||
dependencies = [
|
|
||||||
"unicode-ident",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "quote"
|
|
||||||
version = "1.0.21"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "bbe448f377a7d6961e30f5955f9b8d106c3f5e449d493ee1b125c1d43c2b5179"
|
|
||||||
dependencies = [
|
|
||||||
"proc-macro2",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "rand"
|
|
||||||
version = "0.6.5"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "6d71dacdc3c88c1fde3885a3be3fbab9f35724e6ce99467f7d9c5026132184ca"
|
|
||||||
dependencies = [
|
|
||||||
"autocfg 0.1.8",
|
|
||||||
"libc",
|
|
||||||
"rand_chacha",
|
|
||||||
"rand_core 0.4.2",
|
|
||||||
"rand_hc",
|
|
||||||
"rand_isaac",
|
|
||||||
"rand_jitter",
|
|
||||||
"rand_os",
|
|
||||||
"rand_pcg",
|
|
||||||
"rand_xorshift",
|
|
||||||
"winapi",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "rand_chacha"
|
|
||||||
version = "0.1.1"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "556d3a1ca6600bfcbab7c7c91ccb085ac7fbbcd70e008a98742e7847f4f7bcef"
|
|
||||||
dependencies = [
|
|
||||||
"autocfg 0.1.8",
|
|
||||||
"rand_core 0.3.1",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "rand_core"
|
|
||||||
version = "0.3.1"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "7a6fdeb83b075e8266dcc8762c22776f6877a63111121f5f8c7411e5be7eed4b"
|
|
||||||
dependencies = [
|
|
||||||
"rand_core 0.4.2",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "rand_core"
|
|
||||||
version = "0.4.2"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "9c33a3c44ca05fa6f1807d8e6743f3824e8509beca625669633be0acbdf509dc"
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "rand_hc"
|
|
||||||
version = "0.1.0"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "7b40677c7be09ae76218dc623efbf7b18e34bced3f38883af07bb75630a21bc4"
|
|
||||||
dependencies = [
|
|
||||||
"rand_core 0.3.1",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "rand_isaac"
|
|
||||||
version = "0.1.1"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "ded997c9d5f13925be2a6fd7e66bf1872597f759fd9dd93513dd7e92e5a5ee08"
|
|
||||||
dependencies = [
|
|
||||||
"rand_core 0.3.1",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "rand_jitter"
|
|
||||||
version = "0.1.4"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "1166d5c91dc97b88d1decc3285bb0a99ed84b05cfd0bc2341bdf2d43fc41e39b"
|
|
||||||
dependencies = [
|
|
||||||
"libc",
|
|
||||||
"rand_core 0.4.2",
|
|
||||||
"winapi",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "rand_os"
|
|
||||||
version = "0.1.3"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "7b75f676a1e053fc562eafbb47838d67c84801e38fc1ba459e8f180deabd5071"
|
|
||||||
dependencies = [
|
|
||||||
"cloudabi",
|
|
||||||
"fuchsia-cprng",
|
|
||||||
"libc",
|
|
||||||
"rand_core 0.4.2",
|
|
||||||
"rdrand",
|
|
||||||
"winapi",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "rand_pcg"
|
|
||||||
version = "0.1.2"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "abf9b09b01790cfe0364f52bf32995ea3c39f4d2dd011eac241d2914146d0b44"
|
|
||||||
dependencies = [
|
|
||||||
"autocfg 0.1.8",
|
|
||||||
"rand_core 0.4.2",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "rand_xorshift"
|
|
||||||
version = "0.1.1"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "cbf7e9e623549b0e21f6e97cf8ecf247c1a8fd2e8a992ae265314300b2455d5c"
|
|
||||||
dependencies = [
|
|
||||||
"rand_core 0.3.1",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "rdrand"
|
|
||||||
version = "0.4.0"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "678054eb77286b51581ba43620cc911abf02758c91f93f479767aed0f90458b2"
|
|
||||||
dependencies = [
|
|
||||||
"rand_core 0.3.1",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "regex"
|
|
||||||
version = "1.6.0"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "4c4eb3267174b8c6c2f654116623910a0fef09c4753f8dd83db29c48a0df988b"
|
|
||||||
dependencies = [
|
|
||||||
"aho-corasick",
|
|
||||||
"memchr",
|
|
||||||
"regex-syntax",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "regex-syntax"
|
|
||||||
version = "0.6.27"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "a3f87b73ce11b1619a3c6332f45341e0047173771e8b8b73f87bfeefb7b56244"
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "ring"
|
|
||||||
version = "0.16.20"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "3053cf52e236a3ed746dfc745aa9cacf1b791d846bdaf412f60a8d7d6e17c8fc"
|
|
||||||
dependencies = [
|
|
||||||
"cc",
|
|
||||||
"libc",
|
|
||||||
"once_cell",
|
|
||||||
"spin",
|
|
||||||
"untrusted",
|
|
||||||
"web-sys",
|
|
||||||
"winapi",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "rng256"
|
|
||||||
version = "0.1.0"
|
|
||||||
dependencies = [
|
|
||||||
"arrayref",
|
|
||||||
"libtock_drivers",
|
|
||||||
"rand",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "ryu"
|
|
||||||
version = "1.0.11"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "4501abdff3ae82a1c1b477a17252eb69cee9e66eb915c1abaa4f44d873df9f09"
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "serde"
|
|
||||||
version = "1.0.144"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "0f747710de3dcd43b88c9168773254e809d8ddbdf9653b84e2554ab219f17860"
|
|
||||||
dependencies = [
|
|
||||||
"serde_derive",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "serde_derive"
|
|
||||||
version = "1.0.144"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "94ed3a816fb1d101812f83e789f888322c34e291f894f19590dc310963e87a00"
|
|
||||||
dependencies = [
|
|
||||||
"proc-macro2",
|
|
||||||
"quote",
|
|
||||||
"syn",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "serde_json"
|
|
||||||
version = "1.0.69"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "e466864e431129c7e0d3476b92f20458e5879919a0596c6472738d9fa2d342f8"
|
|
||||||
dependencies = [
|
|
||||||
"itoa",
|
|
||||||
"ryu",
|
|
||||||
"serde",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "spin"
|
|
||||||
version = "0.5.2"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "6e63cff320ae2c57904679ba7cb63280a3dc4613885beafb148ee7bf9aa9042d"
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "subtle"
|
|
||||||
version = "2.4.1"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "6bdef32e8150c2a081110b42772ffe7d7c9032b606bc226c8260fd97e0976601"
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "syn"
|
|
||||||
version = "1.0.100"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "52205623b1b0f064a4e71182c3b18ae902267282930c6d5462c91b859668426e"
|
|
||||||
dependencies = [
|
|
||||||
"proc-macro2",
|
|
||||||
"quote",
|
|
||||||
"unicode-ident",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "unicode-ident"
|
|
||||||
version = "1.0.4"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "dcc811dc4066ac62f84f11307873c4850cb653bfa9b1719cee2bd2204a4bc5dd"
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "untrusted"
|
|
||||||
version = "0.7.1"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "a156c684c91ea7d62626509bce3cb4e1d9ed5c4d978f7b4352658f96a4c26b4a"
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "wasm-bindgen"
|
|
||||||
version = "0.2.80"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "27370197c907c55e3f1a9fbe26f44e937fe6451368324e009cba39e139dc08ad"
|
|
||||||
dependencies = [
|
|
||||||
"cfg-if",
|
|
||||||
"wasm-bindgen-macro",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "wasm-bindgen-backend"
|
|
||||||
version = "0.2.80"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "53e04185bfa3a779273da532f5025e33398409573f348985af9a1cbf3774d3f4"
|
|
||||||
dependencies = [
|
|
||||||
"bumpalo",
|
|
||||||
"lazy_static",
|
|
||||||
"log",
|
|
||||||
"proc-macro2",
|
|
||||||
"quote",
|
|
||||||
"syn",
|
|
||||||
"wasm-bindgen-shared",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "wasm-bindgen-macro"
|
|
||||||
version = "0.2.80"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "17cae7ff784d7e83a2fe7611cfe766ecf034111b49deb850a3dc7699c08251f5"
|
|
||||||
dependencies = [
|
|
||||||
"quote",
|
|
||||||
"wasm-bindgen-macro-support",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "wasm-bindgen-macro-support"
|
|
||||||
version = "0.2.80"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "99ec0dc7a4756fffc231aab1b9f2f578d23cd391390ab27f952ae0c9b3ece20b"
|
|
||||||
dependencies = [
|
|
||||||
"proc-macro2",
|
|
||||||
"quote",
|
|
||||||
"syn",
|
|
||||||
"wasm-bindgen-backend",
|
|
||||||
"wasm-bindgen-shared",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "wasm-bindgen-shared"
|
|
||||||
version = "0.2.80"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "d554b7f530dee5964d9a9468d95c1f8b8acae4f282807e7d27d4b03099a46744"
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "web-sys"
|
|
||||||
version = "0.3.57"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "7b17e741662c70c8bd24ac5c5b18de314a2c26c32bf8346ee1e6f53de919c283"
|
|
||||||
dependencies = [
|
|
||||||
"js-sys",
|
|
||||||
"wasm-bindgen",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "winapi"
|
|
||||||
version = "0.3.9"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419"
|
|
||||||
dependencies = [
|
|
||||||
"winapi-i686-pc-windows-gnu",
|
|
||||||
"winapi-x86_64-pc-windows-gnu",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "winapi-i686-pc-windows-gnu"
|
|
||||||
version = "0.4.0"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "winapi-x86_64-pc-windows-gnu"
|
|
||||||
version = "0.4.0"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
|
|
||||||
@@ -10,10 +10,8 @@ license = "Apache-2.0"
|
|||||||
edition = "2018"
|
edition = "2018"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
rng256 = { path = "../rng256" }
|
|
||||||
arrayref = "0.3.6"
|
arrayref = "0.3.6"
|
||||||
subtle = { version = "2.2.3", default-features = false, features = ["nightly"] }
|
subtle = { version = "2.2.3", default-features = false, features = ["nightly"] }
|
||||||
dilithium = { path = "../../third_party/dilithium" }
|
|
||||||
byteorder = { version = "1", default-features = false }
|
byteorder = { version = "1", default-features = false }
|
||||||
hex = { version = "0.3.2", default-features = false, optional = true }
|
hex = { version = "0.3.2", default-features = false, optional = true }
|
||||||
ring = { version = "0.16.11", optional = true }
|
ring = { version = "0.16.11", optional = true }
|
||||||
@@ -21,7 +19,8 @@ untrusted = { version = "0.7.0", optional = true }
|
|||||||
serde = { version = "1.0", optional = true, features = ["derive"] }
|
serde = { version = "1.0", optional = true, features = ["derive"] }
|
||||||
serde_json = { version = "=1.0.69", optional = true }
|
serde_json = { version = "=1.0.69", optional = true }
|
||||||
regex = { version = "1", optional = true }
|
regex = { version = "1", optional = true }
|
||||||
|
rand_core = "0.6.4"
|
||||||
|
zeroize = { version = "1.5.7", features = ["derive"] }
|
||||||
|
|
||||||
[features]
|
[features]
|
||||||
std = ["hex", "ring", "rng256/std", "untrusted", "serde", "serde_json", "regex"]
|
std = ["hex", "ring", "untrusted", "serde", "serde_json", "regex", "rand_core/getrandom"]
|
||||||
with_ctap1 = []
|
|
||||||
|
|||||||
@@ -12,18 +12,29 @@
|
|||||||
// See the License for the specific language governing permissions and
|
// See the License for the specific language governing permissions and
|
||||||
// limitations under the License.
|
// limitations under the License.
|
||||||
|
|
||||||
|
//! A portable and naive textbook implementation of AES-256
|
||||||
|
|
||||||
use super::util::{xor_block_16, Block16};
|
use super::util::{xor_block_16, Block16};
|
||||||
use arrayref::{array_mut_ref, array_ref};
|
use arrayref::{array_mut_ref, array_ref};
|
||||||
|
use zeroize::Zeroize;
|
||||||
|
|
||||||
/** A portable and naive textbook implementation of AES-256 **/
|
|
||||||
type Word = [u8; 4];
|
type Word = [u8; 4];
|
||||||
|
|
||||||
/** This structure caches the round keys, to avoid re-computing the key schedule for each block. **/
|
/// Encryption key for AES256.
|
||||||
|
///
|
||||||
|
/// Never call zeroize explicitly, to not invalidate any invariants.
|
||||||
|
#[derive(Zeroize)]
|
||||||
pub struct EncryptionKey {
|
pub struct EncryptionKey {
|
||||||
|
// This structure caches the round keys, to avoid re-computing the key schedule for each block.
|
||||||
enc_round_keys: [Block16; 15],
|
enc_round_keys: [Block16; 15],
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Decryption key for AES256.
|
||||||
|
///
|
||||||
|
/// Never call zeroize explicitly, to not invalidate any invariants.
|
||||||
|
#[derive(Zeroize)]
|
||||||
pub struct DecryptionKey {
|
pub struct DecryptionKey {
|
||||||
|
// This structure caches the round keys, to avoid re-computing the key schedule for each block.
|
||||||
dec_round_keys: [Block16; 15],
|
dec_round_keys: [Block16; 15],
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -14,11 +14,14 @@
|
|||||||
|
|
||||||
use super::int256::{Digit, Int256};
|
use super::int256::{Digit, Int256};
|
||||||
use core::ops::Mul;
|
use core::ops::Mul;
|
||||||
use rng256::Rng256;
|
use rand_core::RngCore;
|
||||||
use subtle::{self, Choice, ConditionallySelectable, CtOption};
|
use subtle::{self, Choice, ConditionallySelectable, CtOption};
|
||||||
|
use zeroize::Zeroize;
|
||||||
|
|
||||||
// An exponent on the elliptic curve, that is an element modulo the curve order N.
|
/// An exponent on the elliptic curve, that is an element modulo the curve order N.
|
||||||
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
|
///
|
||||||
|
/// Never call zeroize explicitly, to not invalidate any invariants.
|
||||||
|
#[derive(Clone, Copy, Debug, PartialEq, Eq, Zeroize)]
|
||||||
// TODO: remove this Default once https://github.com/dalek-cryptography/subtle/issues/63 is
|
// TODO: remove this Default once https://github.com/dalek-cryptography/subtle/issues/63 is
|
||||||
// resolved.
|
// resolved.
|
||||||
#[derive(Default)]
|
#[derive(Default)]
|
||||||
@@ -90,8 +93,10 @@ impl Mul for &ExponentP256 {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// A non-zero exponent on the elliptic curve.
|
/// A non-zero exponent on the elliptic curve.
|
||||||
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
|
///
|
||||||
|
/// Never call zeroize explicitly, to not invalidate any invariants.
|
||||||
|
#[derive(Clone, Copy, Debug, PartialEq, Eq, Zeroize)]
|
||||||
// TODO: remove this Default once https://github.com/dalek-cryptography/subtle/issues/63 is
|
// TODO: remove this Default once https://github.com/dalek-cryptography/subtle/issues/63 is
|
||||||
// resolved.
|
// resolved.
|
||||||
#[derive(Default)]
|
#[derive(Default)]
|
||||||
@@ -112,7 +117,7 @@ impl NonZeroExponentP256 {
|
|||||||
// Generates a uniformly distributed element 0 < k < N
|
// Generates a uniformly distributed element 0 < k < N
|
||||||
pub fn gen_uniform<R>(r: &mut R) -> NonZeroExponentP256
|
pub fn gen_uniform<R>(r: &mut R) -> NonZeroExponentP256
|
||||||
where
|
where
|
||||||
R: Rng256,
|
R: RngCore,
|
||||||
{
|
{
|
||||||
loop {
|
loop {
|
||||||
let x = Int256::gen_uniform_256(r);
|
let x = Int256::gen_uniform_256(r);
|
||||||
@@ -293,57 +298,4 @@ pub mod test {
|
|||||||
assert_eq!(ONE.inv(), ONE);
|
assert_eq!(ONE.inv(), ONE);
|
||||||
assert_eq!(N_MIN_1.inv(), N_MIN_1);
|
assert_eq!(N_MIN_1.inv(), N_MIN_1);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** RNG **/
|
|
||||||
// Mock rng that samples through a list of values, then panics.
|
|
||||||
struct StressTestingRng {
|
|
||||||
values: Vec<Int256>,
|
|
||||||
index: usize,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl StressTestingRng {
|
|
||||||
pub fn new(values: Vec<Int256>) -> StressTestingRng {
|
|
||||||
StressTestingRng { values, index: 0 }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Rng256 for StressTestingRng {
|
|
||||||
// This function is unused, as we redefine gen_uniform_u32x8.
|
|
||||||
fn fill_bytes(&mut self, _buf: &mut [u8]) {
|
|
||||||
unreachable!()
|
|
||||||
}
|
|
||||||
|
|
||||||
// This function is unused, as we redefine gen_uniform_u32x8.
|
|
||||||
fn gen_uniform_u8x32(&mut self) -> [u8; 32] {
|
|
||||||
unreachable!()
|
|
||||||
}
|
|
||||||
|
|
||||||
fn gen_uniform_u32x8(&mut self) -> [u32; 8] {
|
|
||||||
let result = self.values[self.index].digits();
|
|
||||||
self.index += 1;
|
|
||||||
result
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn test_uniform_non_zero_is_below_n() {
|
|
||||||
let mut rng = StressTestingRng::new(vec![
|
|
||||||
Int256::new([
|
|
||||||
0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
|
|
||||||
0xffffffff,
|
|
||||||
]),
|
|
||||||
Int256::N,
|
|
||||||
N_MIN_1.to_int(),
|
|
||||||
Int256::N_MIN_2,
|
|
||||||
]);
|
|
||||||
|
|
||||||
assert_eq!(NonZeroExponentP256::gen_uniform(&mut rng), N_MIN_1);
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn test_uniform_n_is_above_zero() {
|
|
||||||
let mut rng = StressTestingRng::new(vec![Int256::ZERO]);
|
|
||||||
|
|
||||||
assert_eq!(NonZeroExponentP256::gen_uniform(&mut rng), ONE);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -15,12 +15,16 @@
|
|||||||
use super::int256::{Digit, Int256};
|
use super::int256::{Digit, Int256};
|
||||||
use core::ops::Mul;
|
use core::ops::Mul;
|
||||||
use subtle::Choice;
|
use subtle::Choice;
|
||||||
|
use zeroize::Zeroize;
|
||||||
|
|
||||||
// A field element on the elliptic curve, that is an element modulo the prime P.
|
/// A field element on the elliptic curve, that is an element modulo the prime P.
|
||||||
// This is the format used to serialize coordinates of points on the curve.
|
///
|
||||||
// This implements enough methods to validate points and to convert them to/from the Montgomery
|
/// This is the format used to serialize coordinates of points on the curve.
|
||||||
// form, which is more convenient to operate on.
|
/// This implements enough methods to validate points and to convert them to/from the Montgomery
|
||||||
#[derive(Clone, Copy, PartialEq, Eq)]
|
/// form, which is more convenient to operate on.
|
||||||
|
///
|
||||||
|
/// Never call zeroize explicitly, to not invalidate any invariants.
|
||||||
|
#[derive(Clone, Copy, PartialEq, Eq, Zeroize)]
|
||||||
pub struct GFP256 {
|
pub struct GFP256 {
|
||||||
int: Int256,
|
int: Int256,
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -17,8 +17,9 @@ use alloc::vec::Vec;
|
|||||||
use arrayref::{array_mut_ref, array_ref};
|
use arrayref::{array_mut_ref, array_ref};
|
||||||
use byteorder::{BigEndian, ByteOrder};
|
use byteorder::{BigEndian, ByteOrder};
|
||||||
use core::ops::{Add, AddAssign, Sub, SubAssign};
|
use core::ops::{Add, AddAssign, Sub, SubAssign};
|
||||||
use rng256::Rng256;
|
use rand_core::RngCore;
|
||||||
use subtle::{self, Choice, ConditionallySelectable, ConstantTimeEq};
|
use subtle::{self, Choice, ConditionallySelectable, ConstantTimeEq};
|
||||||
|
use zeroize::Zeroize;
|
||||||
|
|
||||||
const BITS_PER_DIGIT: usize = 32;
|
const BITS_PER_DIGIT: usize = 32;
|
||||||
const BYTES_PER_DIGIT: usize = BITS_PER_DIGIT >> 3;
|
const BYTES_PER_DIGIT: usize = BITS_PER_DIGIT >> 3;
|
||||||
@@ -29,7 +30,10 @@ pub type Digit = u32;
|
|||||||
type DoubleDigit = u64;
|
type DoubleDigit = u64;
|
||||||
type SignedDoubleDigit = i64;
|
type SignedDoubleDigit = i64;
|
||||||
|
|
||||||
#[derive(Clone, Copy, PartialEq, Eq)]
|
/// Big integer implementation with 256 bits.
|
||||||
|
///
|
||||||
|
/// Never call zeroize explicitly, to not invalidate any invariants.
|
||||||
|
#[derive(Clone, Copy, PartialEq, Eq, Zeroize)]
|
||||||
// TODO: remove this Default once https://github.com/dalek-cryptography/subtle/issues/63 is
|
// TODO: remove this Default once https://github.com/dalek-cryptography/subtle/issues/63 is
|
||||||
// resolved.
|
// resolved.
|
||||||
#[derive(Default)]
|
#[derive(Default)]
|
||||||
@@ -119,11 +123,13 @@ impl Int256 {
|
|||||||
// Generates a uniformly distributed integer 0 <= x < 2^256
|
// Generates a uniformly distributed integer 0 <= x < 2^256
|
||||||
pub fn gen_uniform_256<R>(r: &mut R) -> Int256
|
pub fn gen_uniform_256<R>(r: &mut R) -> Int256
|
||||||
where
|
where
|
||||||
R: Rng256,
|
R: RngCore,
|
||||||
{
|
{
|
||||||
Int256 {
|
let mut digits = [0; NDIGITS];
|
||||||
digits: r.gen_uniform_u32x8(),
|
for i in 0..NDIGITS {
|
||||||
|
digits[i] = r.next_u32();
|
||||||
}
|
}
|
||||||
|
Int256 { digits }
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Serialization **/
|
/** Serialization **/
|
||||||
|
|||||||
@@ -17,13 +17,16 @@ use super::int256::Int256;
|
|||||||
use super::precomputed;
|
use super::precomputed;
|
||||||
use core::ops::{Add, Mul, Sub};
|
use core::ops::{Add, Mul, Sub};
|
||||||
use subtle::{Choice, ConditionallySelectable, ConstantTimeEq};
|
use subtle::{Choice, ConditionallySelectable, ConstantTimeEq};
|
||||||
|
use zeroize::Zeroize;
|
||||||
|
|
||||||
pub const NLIMBS: usize = 9;
|
pub const NLIMBS: usize = 9;
|
||||||
pub const BOTTOM_28_BITS: u32 = 0x0fff_ffff;
|
pub const BOTTOM_28_BITS: u32 = 0x0fff_ffff;
|
||||||
pub const BOTTOM_29_BITS: u32 = 0x1fff_ffff;
|
pub const BOTTOM_29_BITS: u32 = 0x1fff_ffff;
|
||||||
|
|
||||||
/** Field element on the secp256r1 curve, represented in Montgomery form **/
|
/// Field element on the secp256r1 curve, represented in Montgomery form.
|
||||||
#[derive(Clone, Copy)]
|
///
|
||||||
|
/// Never call zeroize explicitly, to not invalidate any invariants.
|
||||||
|
#[derive(Clone, Copy, Zeroize)]
|
||||||
pub struct Montgomery {
|
pub struct Montgomery {
|
||||||
// The 9 limbs use 28 or 29 bits, alternatively: even limbs use 29 bits, odd limbs use 28 bits.
|
// The 9 limbs use 28 or 29 bits, alternatively: even limbs use 29 bits, odd limbs use 28 bits.
|
||||||
// The Montgomery form stores a field element x as (x * 2^257) mod P.
|
// The Montgomery form stores a field element x as (x * 2^257) mod P.
|
||||||
|
|||||||
@@ -21,11 +21,15 @@ use arrayref::array_mut_ref;
|
|||||||
use arrayref::array_ref;
|
use arrayref::array_ref;
|
||||||
use core::ops::Add;
|
use core::ops::Add;
|
||||||
use subtle::{Choice, ConditionallySelectable, ConstantTimeEq};
|
use subtle::{Choice, ConditionallySelectable, ConstantTimeEq};
|
||||||
|
use zeroize::Zeroize;
|
||||||
|
|
||||||
// A point on the elliptic curve is represented by two field elements.
|
/// A point on the elliptic curve, represented by two field elements.
|
||||||
// The "direct" representation with GFP256 (integer modulo p) is used for serialization of public
|
///
|
||||||
// keys.
|
/// The "direct" representation with GFP256 (integer modulo p) is used for serialization of public
|
||||||
#[derive(Clone, Copy, PartialEq, Eq)]
|
/// keys.
|
||||||
|
///
|
||||||
|
/// Never call zeroize explicitly, to not invalidate any invariants.
|
||||||
|
#[derive(Clone, Copy, Zeroize)]
|
||||||
pub struct PointP256 {
|
pub struct PointP256 {
|
||||||
x: GFP256,
|
x: GFP256,
|
||||||
y: GFP256,
|
y: GFP256,
|
||||||
@@ -128,12 +132,15 @@ impl PointP256 {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// A point on the elliptic curve in projective form.
|
/// A point on the elliptic curve in projective form.
|
||||||
// This uses Montgomery representation for field elements.
|
///
|
||||||
// This is in projective coordinates, i.e. it represents the point { x: x / z, y: y / z }.
|
/// This uses Montgomery representation for field elements.
|
||||||
// This representation is more convenient to implement complete formulas for elliptic curve
|
/// This is in projective coordinates, i.e. it represents the point { x: x / z, y: y / z }.
|
||||||
// arithmetic.
|
/// This representation is more convenient to implement complete formulas for elliptic curve
|
||||||
#[derive(Clone, Copy)]
|
/// arithmetic.
|
||||||
|
///
|
||||||
|
/// Never call zeroize explicitly, to not invalidate any invariants.
|
||||||
|
#[derive(Clone, Copy, Zeroize)]
|
||||||
pub struct PointProjective {
|
pub struct PointProjective {
|
||||||
x: Montgomery,
|
x: Montgomery,
|
||||||
y: Montgomery,
|
y: Montgomery,
|
||||||
@@ -150,8 +157,10 @@ impl ConditionallySelectable for PointProjective {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Equivalent to PointProjective { x, y, z: 1 }
|
/// Equivalent to PointProjective { x, y, z: 1 }
|
||||||
#[derive(Clone, Copy)]
|
///
|
||||||
|
/// Never call zeroize explicitly, to not invalidate any invariants.
|
||||||
|
#[derive(Clone, Copy, Zeroize)]
|
||||||
pub struct PointAffine {
|
pub struct PointAffine {
|
||||||
x: Montgomery,
|
x: Montgomery,
|
||||||
y: Montgomery,
|
y: Montgomery,
|
||||||
@@ -548,6 +557,12 @@ impl core::fmt::Debug for PointP256 {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl PartialEq for PointP256 {
|
||||||
|
fn eq(&self, other: &PointP256) -> bool {
|
||||||
|
self.x == other.x && self.y == other.y
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
pub mod test {
|
pub mod test {
|
||||||
use super::*;
|
use super::*;
|
||||||
|
|||||||
@@ -16,15 +16,23 @@ use super::ec::exponent256::NonZeroExponentP256;
|
|||||||
use super::ec::int256;
|
use super::ec::int256;
|
||||||
use super::ec::int256::Int256;
|
use super::ec::int256::Int256;
|
||||||
use super::ec::point::PointP256;
|
use super::ec::point::PointP256;
|
||||||
use rng256::Rng256;
|
use rand_core::RngCore;
|
||||||
|
use zeroize::Zeroize;
|
||||||
|
|
||||||
pub const NBYTES: usize = int256::NBYTES;
|
pub const NBYTES: usize = int256::NBYTES;
|
||||||
|
|
||||||
|
/// A private key for ECDH.
|
||||||
|
///
|
||||||
|
/// Never call zeroize explicitly, to not invalidate any invariants.
|
||||||
|
#[derive(Zeroize)]
|
||||||
pub struct SecKey {
|
pub struct SecKey {
|
||||||
a: NonZeroExponentP256,
|
a: NonZeroExponentP256,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug, PartialEq)]
|
/// A public key for ECDH.
|
||||||
|
///
|
||||||
|
/// Never call zeroize explicitly, to not invalidate any invariants.
|
||||||
|
#[derive(Clone, Debug, PartialEq, Zeroize)]
|
||||||
pub struct PubKey {
|
pub struct PubKey {
|
||||||
p: PointP256,
|
p: PointP256,
|
||||||
}
|
}
|
||||||
@@ -32,7 +40,7 @@ pub struct PubKey {
|
|||||||
impl SecKey {
|
impl SecKey {
|
||||||
pub fn gensk<R>(rng: &mut R) -> SecKey
|
pub fn gensk<R>(rng: &mut R) -> SecKey
|
||||||
where
|
where
|
||||||
R: Rng256,
|
R: RngCore,
|
||||||
{
|
{
|
||||||
SecKey {
|
SecKey {
|
||||||
a: NonZeroExponentP256::gen_uniform(rng),
|
a: NonZeroExponentP256::gen_uniform(rng),
|
||||||
@@ -70,6 +78,17 @@ impl SecKey {
|
|||||||
p.getx().to_int().to_bin(&mut x);
|
p.getx().to_int().to_bin(&mut x);
|
||||||
x
|
x
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Creates a private key from the exponent's bytes, or None if checks fail.
|
||||||
|
pub fn from_bytes(bytes: &[u8; 32]) -> Option<SecKey> {
|
||||||
|
let a = NonZeroExponentP256::from_int_checked(Int256::from_bin(bytes));
|
||||||
|
// The branching here is fine because all this reveals is whether the key was invalid.
|
||||||
|
if bool::from(a.is_none()) {
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
let a = a.unwrap();
|
||||||
|
Some(SecKey { a })
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl PubKey {
|
impl PubKey {
|
||||||
@@ -99,7 +118,7 @@ impl PubKey {
|
|||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod test {
|
mod test {
|
||||||
use super::*;
|
use super::*;
|
||||||
use rng256::ThreadRng256;
|
use rand_core::OsRng;
|
||||||
|
|
||||||
// Run more test iterations in release mode, as the code should be faster.
|
// Run more test iterations in release mode, as the code should be faster.
|
||||||
#[cfg(not(debug_assertions))]
|
#[cfg(not(debug_assertions))]
|
||||||
@@ -110,7 +129,7 @@ mod test {
|
|||||||
/** Test that key generation creates valid keys **/
|
/** Test that key generation creates valid keys **/
|
||||||
#[test]
|
#[test]
|
||||||
fn test_gen_pub_is_valid_random() {
|
fn test_gen_pub_is_valid_random() {
|
||||||
let mut rng = ThreadRng256 {};
|
let mut rng = OsRng::default();
|
||||||
|
|
||||||
for _ in 0..ITERATIONS {
|
for _ in 0..ITERATIONS {
|
||||||
let sk = SecKey::gensk(&mut rng);
|
let sk = SecKey::gensk(&mut rng);
|
||||||
@@ -122,7 +141,7 @@ mod test {
|
|||||||
/** Test that the exchanged key is the same on both sides **/
|
/** Test that the exchanged key is the same on both sides **/
|
||||||
#[test]
|
#[test]
|
||||||
fn test_exchange_x_is_symmetric() {
|
fn test_exchange_x_is_symmetric() {
|
||||||
let mut rng = ThreadRng256 {};
|
let mut rng = OsRng::default();
|
||||||
|
|
||||||
for _ in 0..ITERATIONS {
|
for _ in 0..ITERATIONS {
|
||||||
let sk_a = SecKey::gensk(&mut rng);
|
let sk_a = SecKey::gensk(&mut rng);
|
||||||
@@ -135,7 +154,7 @@ mod test {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_exchange_x_bytes_is_symmetric() {
|
fn test_exchange_x_bytes_is_symmetric() {
|
||||||
let mut rng = ThreadRng256 {};
|
let mut rng = OsRng::default();
|
||||||
|
|
||||||
for _ in 0..ITERATIONS {
|
for _ in 0..ITERATIONS {
|
||||||
let sk_a = SecKey::gensk(&mut rng);
|
let sk_a = SecKey::gensk(&mut rng);
|
||||||
|
|||||||
@@ -16,30 +16,37 @@ use super::ec::exponent256::{ExponentP256, NonZeroExponentP256};
|
|||||||
use super::ec::int256;
|
use super::ec::int256;
|
||||||
use super::ec::int256::Int256;
|
use super::ec::int256::Int256;
|
||||||
use super::ec::point::PointP256;
|
use super::ec::point::PointP256;
|
||||||
use super::hmac::hmac_256;
|
|
||||||
use super::Hash256;
|
use super::Hash256;
|
||||||
use alloc::vec;
|
use alloc::vec;
|
||||||
use alloc::vec::Vec;
|
use alloc::vec::Vec;
|
||||||
#[cfg(feature = "std")]
|
use arrayref::{array_mut_ref, array_ref, mut_array_refs};
|
||||||
use arrayref::array_mut_ref;
|
|
||||||
use arrayref::{array_ref, mut_array_refs};
|
|
||||||
use core::marker::PhantomData;
|
use core::marker::PhantomData;
|
||||||
use rng256::Rng256;
|
use rand_core::RngCore;
|
||||||
|
use zeroize::Zeroize;
|
||||||
|
|
||||||
pub const NBYTES: usize = int256::NBYTES;
|
pub const NBYTES: usize = int256::NBYTES;
|
||||||
|
|
||||||
#[derive(Clone, Debug, PartialEq, Eq)]
|
/// A private key for ECDSA.
|
||||||
|
///
|
||||||
|
/// Never call zeroize explicitly, to not invalidate any invariants.
|
||||||
|
#[derive(Clone, Debug, PartialEq, Eq, Zeroize)]
|
||||||
pub struct SecKey {
|
pub struct SecKey {
|
||||||
k: NonZeroExponentP256,
|
k: NonZeroExponentP256,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug, PartialEq, Eq)]
|
/// An ECDSA signature.
|
||||||
|
///
|
||||||
|
/// Never call zeroize explicitly, to not invalidate any invariants.
|
||||||
|
#[derive(Zeroize)]
|
||||||
pub struct Signature {
|
pub struct Signature {
|
||||||
r: NonZeroExponentP256,
|
r: NonZeroExponentP256,
|
||||||
s: NonZeroExponentP256,
|
s: NonZeroExponentP256,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug, PartialEq, Eq)]
|
/// A public key for ECDSA.
|
||||||
|
///
|
||||||
|
/// Never call zeroize explicitly, to not invalidate any invariants.
|
||||||
|
#[derive(Clone, Zeroize)]
|
||||||
pub struct PubKey {
|
pub struct PubKey {
|
||||||
p: PointP256,
|
p: PointP256,
|
||||||
}
|
}
|
||||||
@@ -47,7 +54,7 @@ pub struct PubKey {
|
|||||||
impl SecKey {
|
impl SecKey {
|
||||||
pub fn gensk<R>(rng: &mut R) -> SecKey
|
pub fn gensk<R>(rng: &mut R) -> SecKey
|
||||||
where
|
where
|
||||||
R: Rng256,
|
R: RngCore,
|
||||||
{
|
{
|
||||||
SecKey {
|
SecKey {
|
||||||
k: NonZeroExponentP256::gen_uniform(rng),
|
k: NonZeroExponentP256::gen_uniform(rng),
|
||||||
@@ -68,7 +75,7 @@ impl SecKey {
|
|||||||
pub fn sign_rng<H, R>(&self, msg: &[u8], rng: &mut R) -> Signature
|
pub fn sign_rng<H, R>(&self, msg: &[u8], rng: &mut R) -> Signature
|
||||||
where
|
where
|
||||||
H: Hash256,
|
H: Hash256,
|
||||||
R: Rng256,
|
R: RngCore,
|
||||||
{
|
{
|
||||||
let m = ExponentP256::modn(Int256::from_bin(&H::hash(msg)));
|
let m = ExponentP256::modn(Int256::from_bin(&H::hash(msg)));
|
||||||
|
|
||||||
@@ -211,7 +218,6 @@ impl Signature {
|
|||||||
Some(Signature { r, s })
|
Some(Signature { r, s })
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "std")]
|
|
||||||
pub fn to_bytes(&self, bytes: &mut [u8; Signature::BYTES_LENGTH]) {
|
pub fn to_bytes(&self, bytes: &mut [u8; Signature::BYTES_LENGTH]) {
|
||||||
self.r
|
self.r
|
||||||
.to_int()
|
.to_int()
|
||||||
@@ -223,9 +229,6 @@ impl Signature {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl PubKey {
|
impl PubKey {
|
||||||
#[cfg(feature = "with_ctap1")]
|
|
||||||
const UNCOMPRESSED_LENGTH: usize = 1 + 2 * int256::NBYTES;
|
|
||||||
|
|
||||||
/// Creates a new PubKey from its coordinates on the elliptic curve.
|
/// Creates a new PubKey from its coordinates on the elliptic curve.
|
||||||
pub fn from_coordinates(x: &[u8; NBYTES], y: &[u8; NBYTES]) -> Option<PubKey> {
|
pub fn from_coordinates(x: &[u8; NBYTES], y: &[u8; NBYTES]) -> Option<PubKey> {
|
||||||
PointP256::new_checked_vartime(Int256::from_bin(x), Int256::from_bin(y))
|
PointP256::new_checked_vartime(Int256::from_bin(x), Int256::from_bin(y))
|
||||||
@@ -241,20 +244,6 @@ impl PubKey {
|
|||||||
self.p.to_bytes_uncompressed(bytes);
|
self.p.to_bytes_uncompressed(bytes);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "with_ctap1")]
|
|
||||||
pub fn to_uncompressed(&self) -> [u8; PubKey::UNCOMPRESSED_LENGTH] {
|
|
||||||
// Formatting according to:
|
|
||||||
// https://tools.ietf.org/id/draft-jivsov-ecc-compact-05.html#overview
|
|
||||||
const B0_BYTE_MARKER: u8 = 0x04;
|
|
||||||
let mut representation = [0; PubKey::UNCOMPRESSED_LENGTH];
|
|
||||||
let (marker, x, y) =
|
|
||||||
mut_array_refs![&mut representation, 1, int256::NBYTES, int256::NBYTES];
|
|
||||||
marker[0] = B0_BYTE_MARKER;
|
|
||||||
self.p.getx().to_int().to_bin(x);
|
|
||||||
self.p.gety().to_int().to_bin(y);
|
|
||||||
representation
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Writes the coordinates into the passed in arrays.
|
/// Writes the coordinates into the passed in arrays.
|
||||||
pub fn to_coordinates(&self, x: &mut [u8; NBYTES], y: &mut [u8; NBYTES]) {
|
pub fn to_coordinates(&self, x: &mut [u8; NBYTES], y: &mut [u8; NBYTES]) {
|
||||||
self.p.getx().to_int().to_bin(x);
|
self.p.getx().to_int().to_bin(x);
|
||||||
@@ -277,7 +266,6 @@ impl PubKey {
|
|||||||
ExponentP256::modn(u.to_int()) == *sign.r.as_exponent()
|
ExponentP256::modn(u.to_int()) == *sign.r.as_exponent()
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "std")]
|
|
||||||
pub fn verify_vartime<H>(&self, msg: &[u8], sign: &Signature) -> bool
|
pub fn verify_vartime<H>(&self, msg: &[u8], sign: &Signature) -> bool
|
||||||
where
|
where
|
||||||
H: Hash256,
|
H: Hash256,
|
||||||
@@ -312,15 +300,15 @@ where
|
|||||||
Int256::to_bin(&sk.k.to_int(), contents_k);
|
Int256::to_bin(&sk.k.to_int(), contents_k);
|
||||||
Int256::to_bin(&Int256::from_bin(&h1).modd(&Int256::N), contents_h1);
|
Int256::to_bin(&Int256::from_bin(&h1).modd(&Int256::N), contents_h1);
|
||||||
|
|
||||||
let k = hmac_256::<H>(&k, &contents);
|
let k = H::hmac(&k, &contents);
|
||||||
let v = hmac_256::<H>(&k, &v);
|
let v = H::hmac(&k, &v);
|
||||||
|
|
||||||
let (contents_v, marker, _) = mut_array_refs![&mut contents, 32, 1, 64];
|
let (contents_v, marker, _) = mut_array_refs![&mut contents, 32, 1, 64];
|
||||||
contents_v.copy_from_slice(&v);
|
contents_v.copy_from_slice(&v);
|
||||||
marker[0] = 0x01;
|
marker[0] = 0x01;
|
||||||
|
|
||||||
let k = hmac_256::<H>(&k, &contents);
|
let k = H::hmac(&k, &contents);
|
||||||
let v = hmac_256::<H>(&k, &v);
|
let v = H::hmac(&k, &v);
|
||||||
|
|
||||||
Rfc6979 {
|
Rfc6979 {
|
||||||
k,
|
k,
|
||||||
@@ -332,14 +320,14 @@ where
|
|||||||
fn next(&mut self) -> Int256 {
|
fn next(&mut self) -> Int256 {
|
||||||
// Note: at this step, the logic from RFC 6979 is simplified, because the HMAC produces 256
|
// Note: at this step, the logic from RFC 6979 is simplified, because the HMAC produces 256
|
||||||
// bits and we need 256 bits.
|
// bits and we need 256 bits.
|
||||||
let t = hmac_256::<H>(&self.k, &self.v);
|
let t = H::hmac(&self.k, &self.v);
|
||||||
let result = Int256::from_bin(&t);
|
let result = Int256::from_bin(&t);
|
||||||
|
|
||||||
let mut v1 = [0; 33];
|
let mut v1 = [0; 33];
|
||||||
v1[..32].copy_from_slice(&self.v);
|
v1[..32].copy_from_slice(&self.v);
|
||||||
v1[32] = 0x00;
|
v1[32] = 0x00;
|
||||||
self.k = hmac_256::<H>(&self.k, &v1);
|
self.k = H::hmac(&self.k, &v1);
|
||||||
self.v = hmac_256::<H>(&self.k, &self.v);
|
self.v = H::hmac(&self.k, &self.v);
|
||||||
|
|
||||||
result
|
result
|
||||||
}
|
}
|
||||||
@@ -349,7 +337,7 @@ where
|
|||||||
mod test {
|
mod test {
|
||||||
use super::super::sha256::Sha256;
|
use super::super::sha256::Sha256;
|
||||||
use super::*;
|
use super::*;
|
||||||
use rng256::ThreadRng256;
|
use rand_core::OsRng;
|
||||||
|
|
||||||
// Run more test iterations in release mode, as the code should be faster.
|
// Run more test iterations in release mode, as the code should be faster.
|
||||||
#[cfg(not(debug_assertions))]
|
#[cfg(not(debug_assertions))]
|
||||||
@@ -357,10 +345,16 @@ mod test {
|
|||||||
#[cfg(debug_assertions)]
|
#[cfg(debug_assertions)]
|
||||||
const ITERATIONS: u32 = 500;
|
const ITERATIONS: u32 = 500;
|
||||||
|
|
||||||
|
fn gen_random_message(rng: &mut impl RngCore) -> [u8; 32] {
|
||||||
|
let mut bytes = [0; 32];
|
||||||
|
rng.fill_bytes(&mut bytes);
|
||||||
|
bytes
|
||||||
|
}
|
||||||
|
|
||||||
/** Test that key generation creates valid keys **/
|
/** Test that key generation creates valid keys **/
|
||||||
#[test]
|
#[test]
|
||||||
fn test_genpk_is_valid_random() {
|
fn test_genpk_is_valid_random() {
|
||||||
let mut rng = ThreadRng256 {};
|
let mut rng = OsRng::default();
|
||||||
|
|
||||||
for _ in 0..ITERATIONS {
|
for _ in 0..ITERATIONS {
|
||||||
let sk = SecKey::gensk(&mut rng);
|
let sk = SecKey::gensk(&mut rng);
|
||||||
@@ -372,7 +366,7 @@ mod test {
|
|||||||
/** Serialization **/
|
/** Serialization **/
|
||||||
#[test]
|
#[test]
|
||||||
fn test_seckey_to_bytes_from_bytes() {
|
fn test_seckey_to_bytes_from_bytes() {
|
||||||
let mut rng = ThreadRng256 {};
|
let mut rng = OsRng::default();
|
||||||
|
|
||||||
for _ in 0..ITERATIONS {
|
for _ in 0..ITERATIONS {
|
||||||
let sk = SecKey::gensk(&mut rng);
|
let sk = SecKey::gensk(&mut rng);
|
||||||
@@ -463,10 +457,10 @@ mod test {
|
|||||||
// Test that signed message hashes are correctly verified.
|
// Test that signed message hashes are correctly verified.
|
||||||
#[test]
|
#[test]
|
||||||
fn test_sign_rfc6979_verify_hash_random() {
|
fn test_sign_rfc6979_verify_hash_random() {
|
||||||
let mut rng = ThreadRng256 {};
|
let mut rng = OsRng::default();
|
||||||
|
|
||||||
for _ in 0..ITERATIONS {
|
for _ in 0..ITERATIONS {
|
||||||
let msg = rng.gen_uniform_u8x32();
|
let msg = gen_random_message(&mut rng);
|
||||||
let sk = SecKey::gensk(&mut rng);
|
let sk = SecKey::gensk(&mut rng);
|
||||||
let pk = sk.genpk();
|
let pk = sk.genpk();
|
||||||
let sign = sk.sign_rfc6979::<Sha256>(&msg);
|
let sign = sk.sign_rfc6979::<Sha256>(&msg);
|
||||||
@@ -478,10 +472,10 @@ mod test {
|
|||||||
// Test that signed messages are correctly verified.
|
// Test that signed messages are correctly verified.
|
||||||
#[test]
|
#[test]
|
||||||
fn test_sign_rfc6979_verify_random() {
|
fn test_sign_rfc6979_verify_random() {
|
||||||
let mut rng = ThreadRng256 {};
|
let mut rng = OsRng::default();
|
||||||
|
|
||||||
for _ in 0..ITERATIONS {
|
for _ in 0..ITERATIONS {
|
||||||
let msg = rng.gen_uniform_u8x32();
|
let msg = gen_random_message(&mut rng);
|
||||||
let sk = SecKey::gensk(&mut rng);
|
let sk = SecKey::gensk(&mut rng);
|
||||||
let pk = sk.genpk();
|
let pk = sk.genpk();
|
||||||
let sign = sk.sign_rfc6979::<Sha256>(&msg);
|
let sign = sk.sign_rfc6979::<Sha256>(&msg);
|
||||||
@@ -492,10 +486,10 @@ mod test {
|
|||||||
// Test that signed messages are correctly verified.
|
// Test that signed messages are correctly verified.
|
||||||
#[test]
|
#[test]
|
||||||
fn test_sign_verify_random() {
|
fn test_sign_verify_random() {
|
||||||
let mut rng = ThreadRng256 {};
|
let mut rng = OsRng::default();
|
||||||
|
|
||||||
for _ in 0..ITERATIONS {
|
for _ in 0..ITERATIONS {
|
||||||
let msg = rng.gen_uniform_u8x32();
|
let msg = gen_random_message(&mut rng);
|
||||||
let sk = SecKey::gensk(&mut rng);
|
let sk = SecKey::gensk(&mut rng);
|
||||||
let pk = sk.genpk();
|
let pk = sk.genpk();
|
||||||
let sign = sk.sign_rng::<Sha256, _>(&msg, &mut rng);
|
let sign = sk.sign_rng::<Sha256, _>(&msg, &mut rng);
|
||||||
@@ -580,10 +574,10 @@ mod test {
|
|||||||
fn test_self_sign_ring_verify() {
|
fn test_self_sign_ring_verify() {
|
||||||
use ring::signature::VerificationAlgorithm;
|
use ring::signature::VerificationAlgorithm;
|
||||||
|
|
||||||
let mut rng = ThreadRng256 {};
|
let mut rng = OsRng::default();
|
||||||
|
|
||||||
for _ in 0..ITERATIONS {
|
for _ in 0..ITERATIONS {
|
||||||
let msg_bytes = rng.gen_uniform_u8x32();
|
let msg_bytes = gen_random_message(&mut rng);
|
||||||
let sk = SecKey::gensk(&mut rng);
|
let sk = SecKey::gensk(&mut rng);
|
||||||
let pk = sk.genpk();
|
let pk = sk.genpk();
|
||||||
let sign = sk.sign_rng::<Sha256, _>(&msg_bytes, &mut rng);
|
let sign = sk.sign_rng::<Sha256, _>(&msg_bytes, &mut rng);
|
||||||
|
|||||||
@@ -17,6 +17,27 @@ use super::Hash256;
|
|||||||
|
|
||||||
const HASH_SIZE: usize = 32;
|
const HASH_SIZE: usize = 32;
|
||||||
|
|
||||||
|
/// Computes the HKDF with the given salt and 256 bit (one block) output.
|
||||||
|
///
|
||||||
|
/// # Arguments
|
||||||
|
///
|
||||||
|
/// * `ikm` - Input keying material
|
||||||
|
/// * `salt` - Byte string that acts as a key
|
||||||
|
/// * `info` - Optional context and application specific information
|
||||||
|
///
|
||||||
|
/// This implementation is equivalent to a standard HKD, with `salt` fixed at a length of
|
||||||
|
/// 32 byte and the output length l as 32.
|
||||||
|
pub fn hkdf_256<H>(ikm: &[u8], salt: &[u8; HASH_SIZE], info: &[u8], okm: &mut [u8; HASH_SIZE])
|
||||||
|
where
|
||||||
|
H: Hash256,
|
||||||
|
{
|
||||||
|
let prk = H::hmac(salt, ikm);
|
||||||
|
// l is implicitly the block size, so we iterate exactly once.
|
||||||
|
let mut t = info.to_vec();
|
||||||
|
t.push(1);
|
||||||
|
hmac_256::<H>(&prk, t.as_slice(), okm);
|
||||||
|
}
|
||||||
|
|
||||||
/// Computes the HKDF with empty salt and 256 bit (one block) output.
|
/// Computes the HKDF with empty salt and 256 bit (one block) output.
|
||||||
///
|
///
|
||||||
/// # Arguments
|
/// # Arguments
|
||||||
@@ -26,16 +47,12 @@ const HASH_SIZE: usize = 32;
|
|||||||
///
|
///
|
||||||
/// This implementation is equivalent to the below hkdf, with `salt` set to the
|
/// This implementation is equivalent to the below hkdf, with `salt` set to the
|
||||||
/// default block of zeros and the output length l as 32.
|
/// default block of zeros and the output length l as 32.
|
||||||
pub fn hkdf_empty_salt_256<H>(ikm: &[u8], info: &[u8]) -> [u8; HASH_SIZE]
|
pub fn hkdf_empty_salt_256<H>(ikm: &[u8], info: &[u8], okm: &mut [u8; HASH_SIZE])
|
||||||
where
|
where
|
||||||
H: Hash256,
|
H: Hash256,
|
||||||
{
|
{
|
||||||
// Salt is a zero block here.
|
// Salt is a zero block here.
|
||||||
let prk = hmac_256::<H>(&[0; HASH_SIZE], ikm);
|
hkdf_256::<H>(ikm, &[0; HASH_SIZE], info, okm);
|
||||||
// l is implicitly the block size, so we iterate exactly once.
|
|
||||||
let mut t = info.to_vec();
|
|
||||||
t.push(1);
|
|
||||||
hmac_256::<H>(&prk, t.as_slice())
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
@@ -49,32 +66,51 @@ mod test {
|
|||||||
// Test vectors generated by pycryptodome using:
|
// Test vectors generated by pycryptodome using:
|
||||||
// HKDF(b'0', 32, b'', SHA256, context=b'\x00').hex()
|
// HKDF(b'0', 32, b'', SHA256, context=b'\x00').hex()
|
||||||
let test_okms = [
|
let test_okms = [
|
||||||
hex::decode("f9be72116cb97f41828210289caafeabde1f3dfb9723bf43538ab18f3666783a")
|
"f9be72116cb97f41828210289caafeabde1f3dfb9723bf43538ab18f3666783a",
|
||||||
.unwrap(),
|
"f50f964f5b94d62fd1da9356ab8662b0a0f5b8e36e277178b69b6ffecf50cf44",
|
||||||
hex::decode("f50f964f5b94d62fd1da9356ab8662b0a0f5b8e36e277178b69b6ffecf50cf44")
|
"fc8772ceb5592d67442dcb4353cdd28519e82d6e55b4cf664b5685252c2d2998",
|
||||||
.unwrap(),
|
"62831b924839a180f53be5461eeea1b89dc21779f50142b5a54df0f0cc86d61a",
|
||||||
hex::decode("fc8772ceb5592d67442dcb4353cdd28519e82d6e55b4cf664b5685252c2d2998")
|
"6991f00a12946a4e3b8315cdcf0132c2ca508fd17b769f08d1454d92d33733e0",
|
||||||
.unwrap(),
|
"0f9bb7dddd1ec61f91d8c4f5369b5870f9d44c4ceabccca1b83f06fec115e4e3",
|
||||||
hex::decode("62831b924839a180f53be5461eeea1b89dc21779f50142b5a54df0f0cc86d61a")
|
"235367e2ab6cca2aba1a666825458dba6b272a215a2537c05feebe4b80dab709",
|
||||||
.unwrap(),
|
"96e8edad661da48d1a133b38c255d33e05555bc9aa442579dea1cd8d8b8d2aef",
|
||||||
hex::decode("6991f00a12946a4e3b8315cdcf0132c2ca508fd17b769f08d1454d92d33733e0")
|
|
||||||
.unwrap(),
|
|
||||||
hex::decode("0f9bb7dddd1ec61f91d8c4f5369b5870f9d44c4ceabccca1b83f06fec115e4e3")
|
|
||||||
.unwrap(),
|
|
||||||
hex::decode("235367e2ab6cca2aba1a666825458dba6b272a215a2537c05feebe4b80dab709")
|
|
||||||
.unwrap(),
|
|
||||||
hex::decode("96e8edad661da48d1a133b38c255d33e05555bc9aa442579dea1cd8d8b8d2aef")
|
|
||||||
.unwrap(),
|
|
||||||
];
|
];
|
||||||
for (i, okm) in test_okms.iter().enumerate() {
|
for (i, okm) in test_okms.iter().enumerate() {
|
||||||
// String of number i.
|
// String of number i.
|
||||||
let ikm = i.to_string();
|
let ikm = i.to_string();
|
||||||
// Byte i.
|
// Byte i.
|
||||||
let info = [i as u8];
|
let info = [i as u8];
|
||||||
assert_eq!(
|
let okm = hex::decode(okm).unwrap();
|
||||||
&hkdf_empty_salt_256::<Sha256>(&ikm.as_bytes(), &info[..]),
|
let mut output = [0; HASH_SIZE];
|
||||||
array_ref!(okm, 0, 32)
|
hkdf_empty_salt_256::<Sha256>(&ikm.as_bytes(), &info[..], &mut output);
|
||||||
);
|
assert_eq!(&output, array_ref!(okm, 0, HASH_SIZE));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_hkdf_256_sha256_vectors() {
|
||||||
|
// Test vectors generated as above, but with salt:
|
||||||
|
let test_okms = [
|
||||||
|
"f9be72116cb97f41828210289caafeabde1f3dfb9723bf43538ab18f3666783a",
|
||||||
|
"a2480a09c7349d76e459f98a8259da40544bfbd2930d357a0f3250ade0acf941",
|
||||||
|
"3904f7bf3615df9512fc6b1af651ed69b43f7fad424f9c718aaab63f377a36b9",
|
||||||
|
"a0027dcffb27d356317199c6e65f153a9286ba114aee2d3cf45bdba83cb7c065",
|
||||||
|
"786d1f89f54668bac443cc6a8887c95d6fbde07702cb4c16d76c452e87c50f79",
|
||||||
|
"8e9a5bdf362c5aec2c31a742dfebd0b7b56e16ab8408d9d0609a4fad06446875",
|
||||||
|
"4a35d3d7c80ff4fab65f7e30d6b305fc7bb39ffe905aabedd6593354f86177b6",
|
||||||
|
"b1121deabd8b4308f3805cda8af991ee976bd8e413bcb6a8dd3fc26ebe2312d2",
|
||||||
|
];
|
||||||
|
for (i, okm) in test_okms.iter().enumerate() {
|
||||||
|
// String of number i.
|
||||||
|
let ikm = i.to_string();
|
||||||
|
// Bytestring of byte i.
|
||||||
|
let salt = [i as u8; 32];
|
||||||
|
// Byte i.
|
||||||
|
let info = [i as u8];
|
||||||
|
let okm = hex::decode(okm).unwrap();
|
||||||
|
let mut output = [0; HASH_SIZE];
|
||||||
|
hkdf_256::<Sha256>(&ikm.as_bytes(), &salt, &info[..], &mut output);
|
||||||
|
assert_eq!(&output, array_ref!(okm, 0, HASH_SIZE));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -24,7 +24,8 @@ pub fn verify_hmac_256<H>(key: &[u8; KEY_SIZE], contents: &[u8], mac: &[u8; HASH
|
|||||||
where
|
where
|
||||||
H: Hash256,
|
H: Hash256,
|
||||||
{
|
{
|
||||||
let expected_mac = hmac_256::<H>(key, contents);
|
let mut expected_mac = [0; HASH_SIZE];
|
||||||
|
hmac_256::<H>(key, contents, &mut expected_mac);
|
||||||
bool::from(expected_mac.ct_eq(mac))
|
bool::from(expected_mac.ct_eq(mac))
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -38,19 +39,23 @@ pub fn verify_hmac_256_first_128bits<H>(
|
|||||||
where
|
where
|
||||||
H: Hash256,
|
H: Hash256,
|
||||||
{
|
{
|
||||||
let expected_mac = hmac_256::<H>(key, contents);
|
let mut expected_mac = [0; HASH_SIZE];
|
||||||
|
hmac_256::<H>(key, contents, &mut expected_mac);
|
||||||
bool::from(array_ref![expected_mac, 0, 16].ct_eq(pin))
|
bool::from(array_ref![expected_mac, 0, 16].ct_eq(pin))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn hmac_256<H>(key: &[u8; KEY_SIZE], contents: &[u8]) -> [u8; HASH_SIZE]
|
pub fn hmac_256<H>(key: &[u8; KEY_SIZE], contents: &[u8], output: &mut [u8; HASH_SIZE])
|
||||||
where
|
where
|
||||||
H: Hash256,
|
H: Hash256,
|
||||||
{
|
{
|
||||||
H::hmac(key, contents)
|
H::hmac_mut(key, contents, output)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn software_hmac_256<H>(key: &[u8; KEY_SIZE], contents: &[u8]) -> [u8; HASH_SIZE]
|
pub(crate) fn software_hmac_256<H>(
|
||||||
where
|
key: &[u8; KEY_SIZE],
|
||||||
|
contents: &[u8],
|
||||||
|
output: &mut [u8; HASH_SIZE],
|
||||||
|
) where
|
||||||
H: Hash256,
|
H: Hash256,
|
||||||
{
|
{
|
||||||
let mut ipad: [u8; BLOCK_SIZE] = [0x36; BLOCK_SIZE];
|
let mut ipad: [u8; BLOCK_SIZE] = [0x36; BLOCK_SIZE];
|
||||||
@@ -64,13 +69,13 @@ where
|
|||||||
let mut ihasher = H::new();
|
let mut ihasher = H::new();
|
||||||
ihasher.update(&ipad);
|
ihasher.update(&ipad);
|
||||||
ihasher.update(contents);
|
ihasher.update(contents);
|
||||||
let ihash = ihasher.finalize();
|
let mut ihash = [0; HASH_SIZE];
|
||||||
|
ihasher.finalize(&mut ihash);
|
||||||
|
|
||||||
let mut ohasher = H::new();
|
let mut ohasher = H::new();
|
||||||
ohasher.update(&opad);
|
ohasher.update(&opad);
|
||||||
ohasher.update(&ihash);
|
ohasher.update(&ihash);
|
||||||
|
ohasher.finalize(output);
|
||||||
ohasher.finalize()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn xor_pads(ipad: &mut [u8; BLOCK_SIZE], opad: &mut [u8; BLOCK_SIZE], key: &[u8; KEY_SIZE]) {
|
fn xor_pads(ipad: &mut [u8; BLOCK_SIZE], opad: &mut [u8; BLOCK_SIZE], key: &[u8; KEY_SIZE]) {
|
||||||
@@ -91,7 +96,8 @@ mod test {
|
|||||||
for len in 0..128 {
|
for len in 0..128 {
|
||||||
let key = [0; KEY_SIZE];
|
let key = [0; KEY_SIZE];
|
||||||
let contents = vec![0; len];
|
let contents = vec![0; len];
|
||||||
let mac = hmac_256::<Sha256>(&key, &contents);
|
let mut mac = [0; HASH_SIZE];
|
||||||
|
hmac_256::<Sha256>(&key, &contents, &mut mac);
|
||||||
assert!(verify_hmac_256::<Sha256>(&key, &contents, &mac));
|
assert!(verify_hmac_256::<Sha256>(&key, &contents, &mac));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -102,7 +108,8 @@ mod test {
|
|||||||
for len in 0..128 {
|
for len in 0..128 {
|
||||||
let key = [0; KEY_SIZE];
|
let key = [0; KEY_SIZE];
|
||||||
let contents = vec![0; len];
|
let contents = vec![0; len];
|
||||||
let mac = hmac_256::<Sha256>(&key, &contents);
|
let mut mac = [0; HASH_SIZE];
|
||||||
|
hmac_256::<Sha256>(&key, &contents, &mut mac);
|
||||||
|
|
||||||
// Check that invalid MACs don't verify, by changing any byte of the valid MAC.
|
// Check that invalid MACs don't verify, by changing any byte of the valid MAC.
|
||||||
for i in 0..HASH_SIZE {
|
for i in 0..HASH_SIZE {
|
||||||
@@ -116,14 +123,21 @@ mod test {
|
|||||||
#[test]
|
#[test]
|
||||||
fn test_hmac_sha256_examples() {
|
fn test_hmac_sha256_examples() {
|
||||||
let key = [0; KEY_SIZE];
|
let key = [0; KEY_SIZE];
|
||||||
|
let mut mac = [0; HASH_SIZE];
|
||||||
|
hmac_256::<Sha256>(&key, &[], &mut mac);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
hmac_256::<Sha256>(&key, &[]),
|
mac,
|
||||||
hex::decode("b613679a0814d9ec772f95d778c35fc5ff1697c493715653c6c712144292c5ad")
|
hex::decode("b613679a0814d9ec772f95d778c35fc5ff1697c493715653c6c712144292c5ad")
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.as_slice()
|
.as_slice()
|
||||||
);
|
);
|
||||||
|
hmac_256::<Sha256>(
|
||||||
|
&key,
|
||||||
|
b"The quick brown fox jumps over the lazy dog",
|
||||||
|
&mut mac,
|
||||||
|
);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
hmac_256::<Sha256>(&key, b"The quick brown fox jumps over the lazy dog"),
|
mac,
|
||||||
hex::decode("fb011e6154a19b9a4c767373c305275a5a69e8b68b0b4c9200c383dced19a416")
|
hex::decode("fb011e6154a19b9a4c767373c305275a5a69e8b68b0b4c9200c383dced19a416")
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.as_slice()
|
.as_slice()
|
||||||
@@ -274,11 +288,10 @@ mod test {
|
|||||||
|
|
||||||
let mut input = Vec::new();
|
let mut input = Vec::new();
|
||||||
let key = [b'A'; KEY_SIZE];
|
let key = [b'A'; KEY_SIZE];
|
||||||
|
let mut mac = [0; HASH_SIZE];
|
||||||
for i in 0..128 {
|
for i in 0..128 {
|
||||||
assert_eq!(
|
hmac_256::<Sha256>(&key, &input, &mut mac);
|
||||||
hmac_256::<Sha256>(&key, &input),
|
assert_eq!(mac, hex::decode(hashes[i] as &[u8]).unwrap().as_slice());
|
||||||
hex::decode(hashes[i] as &[u8]).unwrap().as_slice()
|
|
||||||
);
|
|
||||||
input.push(b'A');
|
input.push(b'A');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,246 +0,0 @@
|
|||||||
// Copyright 2021-2022 Google LLC
|
|
||||||
//
|
|
||||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
// you may not use this file except in compliance with the License.
|
|
||||||
// You may obtain a copy of the License at
|
|
||||||
//
|
|
||||||
// http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
//
|
|
||||||
// Unless required by applicable law or agreed to in writing, software
|
|
||||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
// See the License for the specific language governing permissions and
|
|
||||||
// limitations under the License.
|
|
||||||
|
|
||||||
use super::ecdsa;
|
|
||||||
use alloc::vec::Vec;
|
|
||||||
|
|
||||||
// A label generated uniformly at random from the output space of SHA256.
|
|
||||||
const LABEL: [u8; 32] = [
|
|
||||||
43, 253, 32, 250, 19, 51, 24, 237, 138, 49, 47, 182, 4, 194, 133, 183, 177, 218, 115, 58, 92,
|
|
||||||
117, 45, 172, 156, 5, 214, 176, 248, 103, 55, 216,
|
|
||||||
];
|
|
||||||
|
|
||||||
#[derive(Clone, Debug, PartialEq, Eq)]
|
|
||||||
pub struct SecKey {
|
|
||||||
dilithium_seed: [u8; dilithium::params::SEEDBYTES],
|
|
||||||
ecdsa_sk: ecdsa::SecKey,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Clone, Debug, PartialEq, Eq)]
|
|
||||||
pub struct PubKey {
|
|
||||||
pub dilithium_pk: dilithium::sign::PubKey,
|
|
||||||
pub ecdsa_pk: ecdsa::PubKey,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Clone, Debug, PartialEq, Eq)]
|
|
||||||
pub struct Signature {
|
|
||||||
pub dilithium_sign: Vec<u8>,
|
|
||||||
pub ecdsa_sign: ecdsa::Signature,
|
|
||||||
}
|
|
||||||
|
|
||||||
fn ecdsa_input(msg: &[u8]) -> Vec<u8> {
|
|
||||||
let mut input = LABEL.to_vec();
|
|
||||||
input.extend(msg);
|
|
||||||
return input;
|
|
||||||
}
|
|
||||||
|
|
||||||
fn dilithium_input(msg: &[u8], ecdsa_sign: &ecdsa::Signature) -> Vec<u8> {
|
|
||||||
let mut input = LABEL.to_vec();
|
|
||||||
input.extend(msg);
|
|
||||||
input.extend(ecdsa_sign.to_asn1_der());
|
|
||||||
return input;
|
|
||||||
}
|
|
||||||
|
|
||||||
impl SecKey {
|
|
||||||
pub const BYTES_LENGTH: usize = 32 + dilithium::params::SEEDBYTES;
|
|
||||||
pub fn gensk<R>(rng: &mut R) -> SecKey
|
|
||||||
where
|
|
||||||
R: rng256::Rng256,
|
|
||||||
{
|
|
||||||
let mut seed = [0u8; dilithium::params::SEEDBYTES];
|
|
||||||
rng.fill_bytes(&mut seed);
|
|
||||||
SecKey {
|
|
||||||
dilithium_seed: seed,
|
|
||||||
ecdsa_sk: ecdsa::SecKey::gensk(rng),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn gensk_with_pk<R>(rng: &mut R) -> (SecKey, PubKey)
|
|
||||||
where
|
|
||||||
R: rng256::Rng256,
|
|
||||||
{
|
|
||||||
let mut seed = [0u8; dilithium::params::SEEDBYTES];
|
|
||||||
rng.fill_bytes(&mut seed);
|
|
||||||
let (_, dilithium_pk) = dilithium::sign::SecKey::gensk_with_pk_from_seed(&seed);
|
|
||||||
let ecdsa_sk = ecdsa::SecKey::gensk(rng);
|
|
||||||
let ecdsa_pk = ecdsa_sk.genpk();
|
|
||||||
let sk = SecKey {
|
|
||||||
dilithium_seed: seed,
|
|
||||||
ecdsa_sk,
|
|
||||||
};
|
|
||||||
let pk = PubKey {
|
|
||||||
dilithium_pk,
|
|
||||||
ecdsa_pk,
|
|
||||||
};
|
|
||||||
(sk, pk)
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn genpk(&self) -> PubKey {
|
|
||||||
let (_, dilithium_pk) =
|
|
||||||
dilithium::sign::SecKey::gensk_with_pk_from_seed(&self.dilithium_seed);
|
|
||||||
PubKey {
|
|
||||||
dilithium_pk,
|
|
||||||
ecdsa_pk: self.ecdsa_sk.genpk(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn sign_rfc6979<H>(&self, msg: &[u8]) -> Signature
|
|
||||||
where
|
|
||||||
H: super::Hash256 + super::HashBlockSize64Bytes,
|
|
||||||
{
|
|
||||||
let ecdsa_sign = self.ecdsa_sk.sign_rfc6979::<H>(&ecdsa_input(&msg));
|
|
||||||
let dilithium_sk = dilithium::sign::SecKey::gensk_from_seed(&self.dilithium_seed);
|
|
||||||
// This wastes some stack, we could revert the Dilithium API to take a &mut [u8].
|
|
||||||
let dilithium_sign = dilithium_sk
|
|
||||||
.sign(&dilithium_input(&msg, &ecdsa_sign))
|
|
||||||
.to_vec();
|
|
||||||
|
|
||||||
return Signature {
|
|
||||||
ecdsa_sign,
|
|
||||||
dilithium_sign,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn from_bytes(bytes: &[u8; SecKey::BYTES_LENGTH]) -> Option<SecKey> {
|
|
||||||
let ecdsa_bytes = array_ref!(bytes, 0, 32);
|
|
||||||
let ecdsa_sk = ecdsa::SecKey::from_bytes(&ecdsa_bytes)?;
|
|
||||||
|
|
||||||
let dilithium_seed = array_ref!(bytes, 32, dilithium::params::SEEDBYTES).clone();
|
|
||||||
|
|
||||||
return Some(SecKey {
|
|
||||||
ecdsa_sk,
|
|
||||||
dilithium_seed,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn to_bytes(&self, bytes: &mut [u8; SecKey::BYTES_LENGTH]) {
|
|
||||||
let mut ecdsa_bytes = array_mut_ref!(bytes, 0, 32);
|
|
||||||
self.ecdsa_sk.to_bytes(&mut ecdsa_bytes);
|
|
||||||
let dilithium_bytes = array_mut_ref!(bytes, 32, dilithium::params::SEEDBYTES);
|
|
||||||
dilithium_bytes.copy_from_slice(&self.dilithium_seed);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl PubKey {
|
|
||||||
pub const BYTES_LENGTH: usize = 2 * ecdsa::NBYTES + dilithium::params::PK_SIZE_PACKED;
|
|
||||||
|
|
||||||
pub fn from_bytes(bytes: &[u8; PubKey::BYTES_LENGTH]) -> Option<PubKey> {
|
|
||||||
let ecdsa_x_bytes = array_ref!(bytes, 0, ecdsa::NBYTES);
|
|
||||||
let ecdsa_y_bytes = array_ref!(bytes, ecdsa::NBYTES, ecdsa::NBYTES);
|
|
||||||
|
|
||||||
let ecdsa_pk = ecdsa::PubKey::from_coordinates(&ecdsa_x_bytes, &ecdsa_y_bytes)?;
|
|
||||||
|
|
||||||
let dilithium_bytes = array_ref!(
|
|
||||||
bytes,
|
|
||||||
ecdsa::NBYTES + ecdsa::NBYTES,
|
|
||||||
dilithium::params::PK_SIZE_PACKED
|
|
||||||
)
|
|
||||||
.clone();
|
|
||||||
let dilithium_pk = dilithium::sign::PubKey::from_bytes(&dilithium_bytes);
|
|
||||||
|
|
||||||
Some(PubKey {
|
|
||||||
ecdsa_pk,
|
|
||||||
dilithium_pk,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn to_bytes(&self, bytes: &mut [u8; PubKey::BYTES_LENGTH]) {
|
|
||||||
let mut ecdsa_x_bytes = [0; ecdsa::NBYTES];
|
|
||||||
let mut ecdsa_y_bytes = [0; ecdsa::NBYTES];
|
|
||||||
self.ecdsa_pk
|
|
||||||
.to_coordinates(&mut ecdsa_x_bytes, &mut ecdsa_y_bytes);
|
|
||||||
array_mut_ref!(bytes, 0, ecdsa::NBYTES).clone_from(&ecdsa_x_bytes);
|
|
||||||
array_mut_ref!(bytes, ecdsa::NBYTES, ecdsa::NBYTES).clone_from(&ecdsa_y_bytes);
|
|
||||||
let mut dilithium_bytes = array_mut_ref!(
|
|
||||||
bytes,
|
|
||||||
ecdsa::NBYTES + ecdsa::NBYTES,
|
|
||||||
dilithium::params::PK_SIZE_PACKED
|
|
||||||
);
|
|
||||||
self.dilithium_pk.to_bytes(&mut dilithium_bytes);
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn verify_vartime<H>(&self, msg: &[u8], sign: &Signature) -> bool
|
|
||||||
where
|
|
||||||
H: super::Hash256,
|
|
||||||
{
|
|
||||||
return self
|
|
||||||
.ecdsa_pk
|
|
||||||
.verify_hash_vartime(&H::hash(&ecdsa_input(&msg)), &sign.ecdsa_sign)
|
|
||||||
&& self.dilithium_pk.verify(
|
|
||||||
&dilithium_input(&msg, &sign.ecdsa_sign),
|
|
||||||
array_ref!(sign.dilithium_sign, 0, dilithium::params::SIG_SIZE_PACKED),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Signature {
|
|
||||||
pub const BYTES_LENGTH: usize = 64 + dilithium::params::SIG_SIZE_PACKED;
|
|
||||||
|
|
||||||
/// Converts a signature into the CBOR required byte array representation.
|
|
||||||
///
|
|
||||||
/// This operation consumes the signature to efficiently use memory.
|
|
||||||
pub fn to_asn1_der(self) -> Vec<u8> {
|
|
||||||
let mut bytes = self.ecdsa_sign.to_asn1_der();
|
|
||||||
bytes.reserve_exact(dilithium::params::SIG_SIZE_PACKED);
|
|
||||||
bytes.extend(self.dilithium_sign.into_iter());
|
|
||||||
bytes
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(test)]
|
|
||||||
mod test {
|
|
||||||
extern crate rng256;
|
|
||||||
use super::super::sha256::Sha256;
|
|
||||||
use super::*;
|
|
||||||
use rng256::Rng256;
|
|
||||||
|
|
||||||
pub const ITERATIONS: u32 = 500;
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn test_hybrid_seckey_to_bytes_from_bytes() {
|
|
||||||
let mut rng = rng256::ThreadRng256 {};
|
|
||||||
for _ in 0..ITERATIONS {
|
|
||||||
let sk = SecKey::gensk(&mut rng);
|
|
||||||
let mut bytes = [0; SecKey::BYTES_LENGTH];
|
|
||||||
sk.to_bytes(&mut bytes);
|
|
||||||
let decoded_sk = SecKey::from_bytes(&bytes);
|
|
||||||
assert_eq!(decoded_sk, Some(sk));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn test_hybrid_pubkey_to_bytes_from_bytes() {
|
|
||||||
let mut rng = rng256::ThreadRng256 {};
|
|
||||||
for _ in 0..ITERATIONS {
|
|
||||||
let sk = SecKey::gensk(&mut rng);
|
|
||||||
let pk = sk.genpk();
|
|
||||||
let mut bytes = [0; PubKey::BYTES_LENGTH];
|
|
||||||
pk.to_bytes(&mut bytes);
|
|
||||||
let decoded_pk = PubKey::from_bytes(&bytes);
|
|
||||||
assert_eq!(decoded_pk, Some(pk));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn test_hybrid_sign_rfc6979_verify_vartime() {
|
|
||||||
let mut rng = rng256::ThreadRng256 {};
|
|
||||||
for _ in 0..ITERATIONS {
|
|
||||||
let msg = rng.gen_uniform_u8x32();
|
|
||||||
let sk = SecKey::gensk(&mut rng);
|
|
||||||
let pk = sk.genpk();
|
|
||||||
let sign = sk.sign_rfc6979::<Sha256>(&msg);
|
|
||||||
assert!(pk.verify_vartime::<Sha256>(&msg, &sign));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
// Copyright 2019-2022 Google LLC
|
// Copyright 2019 Google LLC
|
||||||
//
|
//
|
||||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
// you may not use this file except in compliance with the License.
|
// you may not use this file except in compliance with the License.
|
||||||
@@ -16,8 +16,6 @@
|
|||||||
#![feature(wrapping_int_impl)]
|
#![feature(wrapping_int_impl)]
|
||||||
|
|
||||||
extern crate alloc;
|
extern crate alloc;
|
||||||
#[macro_use]
|
|
||||||
extern crate arrayref;
|
|
||||||
|
|
||||||
pub mod aes256;
|
pub mod aes256;
|
||||||
pub mod cbc;
|
pub mod cbc;
|
||||||
@@ -26,30 +24,42 @@ pub mod ecdh;
|
|||||||
pub mod ecdsa;
|
pub mod ecdsa;
|
||||||
pub mod hkdf;
|
pub mod hkdf;
|
||||||
pub mod hmac;
|
pub mod hmac;
|
||||||
pub mod hybrid;
|
|
||||||
pub mod sha256;
|
pub mod sha256;
|
||||||
pub mod util;
|
pub mod util;
|
||||||
|
|
||||||
// Trait for hash functions that returns a 256-bit hash.
|
/// Trait for hash functions that returns a 256-bit hash.
|
||||||
// The type must be Sized (size known at compile time) so that we can instanciate one on the stack
|
///
|
||||||
// in the hash() method.
|
/// When you implement this trait, make sure to implement `hash_mut` and `hmac_mut` first, because
|
||||||
|
/// the default implementations of `hash` and `hmac` rely on it.
|
||||||
pub trait Hash256: Sized {
|
pub trait Hash256: Sized {
|
||||||
fn new() -> Self;
|
fn new() -> Self;
|
||||||
fn update(&mut self, contents: &[u8]);
|
fn update(&mut self, contents: &[u8]);
|
||||||
fn finalize(self) -> [u8; 32];
|
fn finalize(self, output: &mut [u8; 32]);
|
||||||
|
|
||||||
fn hash(contents: &[u8]) -> [u8; 32] {
|
fn hash(contents: &[u8]) -> [u8; 32] {
|
||||||
|
let mut output = [0; 32];
|
||||||
|
Self::hash_mut(contents, &mut output);
|
||||||
|
output
|
||||||
|
}
|
||||||
|
|
||||||
|
fn hash_mut(contents: &[u8], output: &mut [u8; 32]) {
|
||||||
let mut h = Self::new();
|
let mut h = Self::new();
|
||||||
h.update(contents);
|
h.update(contents);
|
||||||
h.finalize()
|
h.finalize(output)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn hmac(key: &[u8; 32], contents: &[u8]) -> [u8; 32] {
|
fn hmac(key: &[u8; 32], contents: &[u8]) -> [u8; 32] {
|
||||||
hmac::software_hmac_256::<Self>(key, contents)
|
let mut output = [0; 32];
|
||||||
|
Self::hmac_mut(key, contents, &mut output);
|
||||||
|
output
|
||||||
|
}
|
||||||
|
|
||||||
|
fn hmac_mut(key: &[u8; 32], contents: &[u8], output: &mut [u8; 32]) {
|
||||||
|
hmac::software_hmac_256::<Self>(key, contents, output);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Trait for hash functions that operate on 64-byte input blocks.
|
/// Trait for hash functions that operate on 64-byte input blocks.
|
||||||
pub trait HashBlockSize64Bytes {
|
pub trait HashBlockSize64Bytes {
|
||||||
type State;
|
type State;
|
||||||
|
|
||||||
|
|||||||
@@ -17,6 +17,7 @@ use arrayref::{array_mut_ref, array_ref};
|
|||||||
use byteorder::{BigEndian, ByteOrder};
|
use byteorder::{BigEndian, ByteOrder};
|
||||||
use core::cell::Cell;
|
use core::cell::Cell;
|
||||||
use core::num::Wrapping;
|
use core::num::Wrapping;
|
||||||
|
use zeroize::Zeroize;
|
||||||
|
|
||||||
const BLOCK_SIZE: usize = 64;
|
const BLOCK_SIZE: usize = 64;
|
||||||
|
|
||||||
@@ -32,6 +33,17 @@ pub struct Sha256 {
|
|||||||
total_len: usize,
|
total_len: usize,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl Drop for Sha256 {
|
||||||
|
// TODO derive Zeroize instead when we upgrade the toolchain
|
||||||
|
fn drop(&mut self) {
|
||||||
|
for s in self.state.iter_mut() {
|
||||||
|
s.0.zeroize();
|
||||||
|
}
|
||||||
|
self.block.zeroize();
|
||||||
|
self.total_len.zeroize();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl Hash256 for Sha256 {
|
impl Hash256 for Sha256 {
|
||||||
fn new() -> Self {
|
fn new() -> Self {
|
||||||
assert!(!BUSY.replace(true));
|
assert!(!BUSY.replace(true));
|
||||||
@@ -72,7 +84,7 @@ impl Hash256 for Sha256 {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn finalize(mut self) -> [u8; 32] {
|
fn finalize(mut self, output: &mut [u8; 32]) {
|
||||||
// Last block and padding.
|
// Last block and padding.
|
||||||
let cursor_in_block = self.total_len % BLOCK_SIZE;
|
let cursor_in_block = self.total_len % BLOCK_SIZE;
|
||||||
self.block[cursor_in_block] = 0x80;
|
self.block[cursor_in_block] = 0x80;
|
||||||
@@ -97,12 +109,10 @@ impl Hash256 for Sha256 {
|
|||||||
Sha256::hash_block(&mut self.state, &self.block);
|
Sha256::hash_block(&mut self.state, &self.block);
|
||||||
|
|
||||||
// Encode the state's 32-bit words into bytes, using big-endian.
|
// Encode the state's 32-bit words into bytes, using big-endian.
|
||||||
let mut result: [u8; 32] = [0; 32];
|
|
||||||
for i in 0..8 {
|
for i in 0..8 {
|
||||||
BigEndian::write_u32(array_mut_ref![result, 4 * i, 4], self.state[i].0);
|
BigEndian::write_u32(array_mut_ref![output, 4 * i, 4], self.state[i].0);
|
||||||
}
|
}
|
||||||
BUSY.set(false);
|
BUSY.set(false);
|
||||||
result
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -272,7 +282,9 @@ mod test {
|
|||||||
h.update(&input[..i]);
|
h.update(&input[..i]);
|
||||||
h.update(&input[i..j]);
|
h.update(&input[i..j]);
|
||||||
h.update(&input[j..]);
|
h.update(&input[j..]);
|
||||||
assert_eq!(h.finalize(), hash.as_slice());
|
let mut digest = [0; 32];
|
||||||
|
h.finalize(&mut digest);
|
||||||
|
assert_eq!(digest, hash.as_slice());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
55
libraries/opensk/Cargo.toml
Normal file
55
libraries/opensk/Cargo.toml
Normal file
@@ -0,0 +1,55 @@
|
|||||||
|
[package]
|
||||||
|
name = "opensk"
|
||||||
|
version = "1.0.0"
|
||||||
|
authors = [
|
||||||
|
"Fabian Kaczmarczyck <kaczmarczyck@google.com>",
|
||||||
|
"Guillaume Endignoux <guillaumee@google.com>",
|
||||||
|
"Jean-Michel Picod <jmichel@google.com>",
|
||||||
|
"Julien Cretin <cretin@google.com>",
|
||||||
|
]
|
||||||
|
license = "Apache-2.0"
|
||||||
|
edition = "2018"
|
||||||
|
rust-version = "1.47"
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
sk-cbor = { path = "../cbor" }
|
||||||
|
crypto = { path = "../crypto" }
|
||||||
|
persistent_store = { path = "../persistent_store" }
|
||||||
|
byteorder = { version = "1", default-features = false }
|
||||||
|
arrayref = "0.3.6"
|
||||||
|
subtle = { version = "2.2", default-features = false, features = ["nightly"] }
|
||||||
|
arbitrary = { version = "0.4.7", features = ["derive"], optional = true }
|
||||||
|
ed25519-compact = { version = "1", default-features = false, optional = true }
|
||||||
|
rand_core = "0.6.4"
|
||||||
|
rand = { version = "0.8.5", default-features = false, optional = true }
|
||||||
|
sha2 = { version = "0.10.6", default-features = false, optional = true }
|
||||||
|
hmac = { version = "0.12.1", default-features = false, optional = true }
|
||||||
|
hkdf = { version = "0.12.3", default-features = false, optional = true }
|
||||||
|
aes = { version = "0.8.2", default-features = false, optional = true }
|
||||||
|
cbc = { version = "0.1.2", default-features = false, optional = true }
|
||||||
|
zeroize = { version = "1.5.7", features = ["derive"] }
|
||||||
|
|
||||||
|
[dependencies.p256]
|
||||||
|
version = "0.13.0"
|
||||||
|
default-features = false
|
||||||
|
features = ["alloc", "ecdh", "ecdsa"]
|
||||||
|
optional = true
|
||||||
|
|
||||||
|
[features]
|
||||||
|
default = ["config_command", "with_ctap1"]
|
||||||
|
config_command = []
|
||||||
|
debug_ctap = []
|
||||||
|
std = ["crypto/std", "persistent_store/std", "rand/std_rng", "config_command"]
|
||||||
|
with_ctap1 = []
|
||||||
|
vendor_hid = []
|
||||||
|
fuzz = ["arbitrary", "std"]
|
||||||
|
ed25519 = ["ed25519-compact"]
|
||||||
|
rust_crypto = ["p256", "sha2", "hmac", "hkdf", "aes", "cbc"]
|
||||||
|
|
||||||
|
[dev-dependencies]
|
||||||
|
enum-iterator = "0.6.0"
|
||||||
|
|
||||||
|
[build-dependencies]
|
||||||
|
sk-cbor = { path = "../cbor" }
|
||||||
|
uuid = { version = "0.8", features = ["v4"] }
|
||||||
|
openssl = "0.10.36"
|
||||||
3
libraries/opensk/fuzz/.gitignore
vendored
Normal file
3
libraries/opensk/fuzz/.gitignore
vendored
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
/artifacts/
|
||||||
|
/corpus/
|
||||||
|
/target/
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "ctap2-fuzz"
|
name = "opensk-fuzz"
|
||||||
version = "0.0.0"
|
version = "0.0.0"
|
||||||
authors = ["Automatically generated"]
|
authors = ["Automatically generated"]
|
||||||
publish = false
|
publish = false
|
||||||
13
libraries/opensk/fuzz/fuzz_helper/Cargo.toml
Normal file
13
libraries/opensk/fuzz/fuzz_helper/Cargo.toml
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
[package]
|
||||||
|
name = "fuzz_helper"
|
||||||
|
version = "0.1.0"
|
||||||
|
authors = ["Mingxiao Guo <mingxguo@google.com>"]
|
||||||
|
license = "Apache-2.0"
|
||||||
|
edition = "2018"
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
arrayref = "0.3.6"
|
||||||
|
opensk = { path = "../..", features = ["fuzz"] }
|
||||||
|
crypto = { path = "../../../crypto", features = ['std'] }
|
||||||
|
sk-cbor = { path = "../../../cbor" }
|
||||||
|
arbitrary = { version = "0.4.7", features = ["derive"] }
|
||||||
@@ -12,27 +12,22 @@
|
|||||||
// See the License for the specific language governing permissions and
|
// See the License for the specific language governing permissions and
|
||||||
// limitations under the License.
|
// limitations under the License.
|
||||||
|
|
||||||
// This explicit "extern crate" is needed to make the linker aware of the
|
|
||||||
// `libtock_alloc_init` symbol.
|
|
||||||
extern crate lang_items;
|
|
||||||
|
|
||||||
use arbitrary::{Arbitrary, Unstructured};
|
use arbitrary::{Arbitrary, Unstructured};
|
||||||
use arrayref::array_ref;
|
use arrayref::array_ref;
|
||||||
use core::convert::TryFrom;
|
use core::convert::TryFrom;
|
||||||
use ctap2::api::customization::is_valid;
|
use opensk::api::customization::is_valid;
|
||||||
use ctap2::clock::CtapInstant;
|
use opensk::ctap::command::{
|
||||||
use ctap2::ctap::command::{
|
|
||||||
AuthenticatorClientPinParameters, AuthenticatorGetAssertionParameters,
|
AuthenticatorClientPinParameters, AuthenticatorGetAssertionParameters,
|
||||||
AuthenticatorMakeCredentialParameters, Command,
|
AuthenticatorMakeCredentialParameters, Command,
|
||||||
};
|
};
|
||||||
use ctap2::ctap::data_formats::EnterpriseAttestationMode;
|
use opensk::ctap::data_formats::EnterpriseAttestationMode;
|
||||||
use ctap2::ctap::hid::{
|
use opensk::ctap::hid::{
|
||||||
ChannelID, CtapHidCommand, HidPacket, HidPacketIterator, Message, MessageAssembler,
|
ChannelID, CtapHidCommand, HidPacket, HidPacketIterator, Message, MessageAssembler,
|
||||||
};
|
};
|
||||||
use ctap2::ctap::{cbor_read, Channel, CtapState};
|
use opensk::ctap::{cbor_read, Channel, CtapState};
|
||||||
use ctap2::env::test::customization::TestCustomization;
|
use opensk::env::test::customization::TestCustomization;
|
||||||
use ctap2::env::test::TestEnv;
|
use opensk::env::test::TestEnv;
|
||||||
use ctap2::{test_helpers, Ctap, Transport};
|
use opensk::{test_helpers, Ctap, Transport};
|
||||||
|
|
||||||
const CHANNEL_BROADCAST: ChannelID = [0xFF, 0xFF, 0xFF, 0xFF];
|
const CHANNEL_BROADCAST: ChannelID = [0xFF, 0xFF, 0xFF, 0xFF];
|
||||||
|
|
||||||
@@ -86,15 +81,11 @@ fn initialize(ctap: &mut Ctap<TestEnv>) -> ChannelID {
|
|||||||
cmd: CtapHidCommand::Init,
|
cmd: CtapHidCommand::Init,
|
||||||
payload: nonce,
|
payload: nonce,
|
||||||
};
|
};
|
||||||
let mut assembler_reply = MessageAssembler::new();
|
let mut assembler_reply = MessageAssembler::default();
|
||||||
let mut result_cid: ChannelID = Default::default();
|
let mut result_cid: ChannelID = Default::default();
|
||||||
for pkt_request in HidPacketIterator::new(message).unwrap() {
|
for pkt_request in HidPacketIterator::new(message).unwrap() {
|
||||||
for pkt_reply in
|
for pkt_reply in ctap.process_hid_packet(&pkt_request, Transport::MainHid) {
|
||||||
ctap.process_hid_packet(&pkt_request, Transport::MainHid, CtapInstant::new(0))
|
if let Ok(Some(result)) = assembler_reply.parse_packet(ctap.env(), &pkt_reply, None) {
|
||||||
{
|
|
||||||
if let Ok(Some(result)) =
|
|
||||||
assembler_reply.parse_packet(ctap.env(), &pkt_reply, CtapInstant::new(0))
|
|
||||||
{
|
|
||||||
result_cid.copy_from_slice(&result.payload[8..12]);
|
result_cid.copy_from_slice(&result.payload[8..12]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -129,13 +120,11 @@ fn is_type(data: &[u8], input_type: InputType) -> bool {
|
|||||||
fn process_message(data: &[u8], ctap: &mut Ctap<TestEnv>) {
|
fn process_message(data: &[u8], ctap: &mut Ctap<TestEnv>) {
|
||||||
let message = raw_to_message(data);
|
let message = raw_to_message(data);
|
||||||
if let Some(hid_packet_iterator) = HidPacketIterator::new(message) {
|
if let Some(hid_packet_iterator) = HidPacketIterator::new(message) {
|
||||||
let mut assembler_reply = MessageAssembler::new();
|
let mut assembler_reply = MessageAssembler::default();
|
||||||
for pkt_request in hid_packet_iterator {
|
for pkt_request in hid_packet_iterator {
|
||||||
for pkt_reply in
|
for pkt_reply in ctap.process_hid_packet(&pkt_request, Transport::MainHid) {
|
||||||
ctap.process_hid_packet(&pkt_request, Transport::MainHid, CtapInstant::new(0))
|
|
||||||
{
|
|
||||||
// Only checks for assembling crashes, not for semantics.
|
// Only checks for assembling crashes, not for semantics.
|
||||||
let _ = assembler_reply.parse_packet(ctap.env(), &pkt_reply, CtapInstant::new(0));
|
let _ = assembler_reply.parse_packet(ctap.env(), &pkt_reply, None);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -147,12 +136,12 @@ fn process_message(data: &[u8], ctap: &mut Ctap<TestEnv>) {
|
|||||||
pub fn process_ctap_any_type(data: &[u8]) -> arbitrary::Result<()> {
|
pub fn process_ctap_any_type(data: &[u8]) -> arbitrary::Result<()> {
|
||||||
let mut unstructured = Unstructured::new(data);
|
let mut unstructured = Unstructured::new(data);
|
||||||
|
|
||||||
let mut env = TestEnv::new();
|
let mut env = TestEnv::default();
|
||||||
env.rng().seed_from_u64(u64::arbitrary(&mut unstructured)?);
|
env.seed_rng_from_u64(u64::arbitrary(&mut unstructured)?);
|
||||||
|
|
||||||
let data = unstructured.take_rest();
|
let data = unstructured.take_rest();
|
||||||
// Initialize ctap state and hid and get the allocated cid.
|
// Initialize ctap state and hid and get the allocated cid.
|
||||||
let mut ctap = Ctap::new(env, CtapInstant::new(0));
|
let mut ctap = Ctap::new(env);
|
||||||
let cid = initialize(&mut ctap);
|
let cid = initialize(&mut ctap);
|
||||||
// Wrap input as message with the allocated cid.
|
// Wrap input as message with the allocated cid.
|
||||||
let mut command = cid.to_vec();
|
let mut command = cid.to_vec();
|
||||||
@@ -179,7 +168,7 @@ fn setup_customization(
|
|||||||
|
|
||||||
fn setup_state(
|
fn setup_state(
|
||||||
unstructured: &mut Unstructured,
|
unstructured: &mut Unstructured,
|
||||||
state: &mut CtapState,
|
state: &mut CtapState<TestEnv>,
|
||||||
env: &mut TestEnv,
|
env: &mut TestEnv,
|
||||||
) -> FuzzResult<()> {
|
) -> FuzzResult<()> {
|
||||||
if bool::arbitrary(unstructured)? {
|
if bool::arbitrary(unstructured)? {
|
||||||
@@ -194,15 +183,15 @@ fn setup_state(
|
|||||||
pub fn process_ctap_specific_type(data: &[u8], input_type: InputType) -> arbitrary::Result<()> {
|
pub fn process_ctap_specific_type(data: &[u8], input_type: InputType) -> arbitrary::Result<()> {
|
||||||
let mut unstructured = Unstructured::new(data);
|
let mut unstructured = Unstructured::new(data);
|
||||||
|
|
||||||
let mut env = TestEnv::new();
|
let mut env = TestEnv::default();
|
||||||
env.rng().seed_from_u64(u64::arbitrary(&mut unstructured)?);
|
env.seed_rng_from_u64(u64::arbitrary(&mut unstructured)?);
|
||||||
|
|
||||||
let data = unstructured.take_rest();
|
let data = unstructured.take_rest();
|
||||||
if !is_type(data, input_type) {
|
if !is_type(data, input_type) {
|
||||||
return Ok(());
|
return Ok(());
|
||||||
}
|
}
|
||||||
// Initialize ctap state and hid and get the allocated cid.
|
// Initialize ctap state and hid and get the allocated cid.
|
||||||
let mut ctap = Ctap::new(env, CtapInstant::new(0));
|
let mut ctap = Ctap::new(env);
|
||||||
let cid = initialize(&mut ctap);
|
let cid = initialize(&mut ctap);
|
||||||
// Wrap input as message with allocated cid and command type.
|
// Wrap input as message with allocated cid and command type.
|
||||||
let mut command = cid.to_vec();
|
let mut command = cid.to_vec();
|
||||||
@@ -228,11 +217,11 @@ pub fn process_ctap_specific_type(data: &[u8], input_type: InputType) -> arbitra
|
|||||||
pub fn process_ctap_structured(data: &[u8], input_type: InputType) -> FuzzResult<()> {
|
pub fn process_ctap_structured(data: &[u8], input_type: InputType) -> FuzzResult<()> {
|
||||||
let unstructured = &mut Unstructured::new(data);
|
let unstructured = &mut Unstructured::new(data);
|
||||||
|
|
||||||
let mut env = TestEnv::new();
|
let mut env = TestEnv::default();
|
||||||
env.rng().seed_from_u64(u64::arbitrary(unstructured)?);
|
env.seed_rng_from_u64(u64::arbitrary(unstructured)?);
|
||||||
setup_customization(unstructured, env.customization_mut())?;
|
setup_customization(unstructured, env.customization_mut())?;
|
||||||
|
|
||||||
let mut state = CtapState::new(&mut env, CtapInstant::new(0));
|
let mut state = CtapState::new(&mut env);
|
||||||
setup_state(unstructured, &mut state, &mut env)?;
|
setup_state(unstructured, &mut state, &mut env)?;
|
||||||
|
|
||||||
let command = match input_type {
|
let command = match input_type {
|
||||||
@@ -255,7 +244,6 @@ pub fn process_ctap_structured(data: &[u8], input_type: InputType) -> FuzzResult
|
|||||||
&mut env,
|
&mut env,
|
||||||
command,
|
command,
|
||||||
Channel::MainHid(ChannelID::arbitrary(unstructured)?),
|
Channel::MainHid(ChannelID::arbitrary(unstructured)?),
|
||||||
CtapInstant::new(0),
|
|
||||||
)
|
)
|
||||||
.ok();
|
.ok();
|
||||||
|
|
||||||
@@ -266,23 +254,20 @@ pub fn process_ctap_structured(data: &[u8], input_type: InputType) -> FuzzResult
|
|||||||
pub fn split_assemble_hid_packets(data: &[u8]) -> arbitrary::Result<()> {
|
pub fn split_assemble_hid_packets(data: &[u8]) -> arbitrary::Result<()> {
|
||||||
let mut unstructured = Unstructured::new(data);
|
let mut unstructured = Unstructured::new(data);
|
||||||
|
|
||||||
let mut env = TestEnv::new();
|
let mut env = TestEnv::default();
|
||||||
env.rng().seed_from_u64(u64::arbitrary(&mut unstructured)?);
|
env.seed_rng_from_u64(u64::arbitrary(&mut unstructured)?);
|
||||||
|
|
||||||
let data = unstructured.take_rest();
|
let data = unstructured.take_rest();
|
||||||
let message = raw_to_message(data);
|
let message = raw_to_message(data);
|
||||||
if let Some(hid_packet_iterator) = HidPacketIterator::new(message.clone()) {
|
if let Some(hid_packet_iterator) = HidPacketIterator::new(message.clone()) {
|
||||||
let mut assembler = MessageAssembler::new();
|
let mut assembler = MessageAssembler::default();
|
||||||
let packets: Vec<HidPacket> = hid_packet_iterator.collect();
|
let packets: Vec<HidPacket> = hid_packet_iterator.collect();
|
||||||
if let Some((last_packet, first_packets)) = packets.split_last() {
|
if let Some((last_packet, first_packets)) = packets.split_last() {
|
||||||
for packet in first_packets {
|
for packet in first_packets {
|
||||||
assert_eq!(
|
assert_eq!(assembler.parse_packet(&mut env, packet, None), Ok(None));
|
||||||
assembler.parse_packet(&mut env, packet, CtapInstant::new(0)),
|
|
||||||
Ok(None)
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
assembler.parse_packet(&mut env, last_packet, CtapInstant::new(0)),
|
assembler.parse_packet(&mut env, last_packet, None),
|
||||||
Ok(Some(message))
|
Ok(Some(message))
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user