Skip to content
New issue

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

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

Already on GitHub? Sign in to your account

Add COSE structure extensions that allow use of predefined cryptographic backends + an OpenSSL based backend. #13

Merged
merged 32 commits into from
Aug 4, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
32 commits
Select commit Hold shift + click to select a range
d3ccc5c
feat: add signing functionality based on openssl impl (in theory)
pulsastrix Jul 15, 2023
5aecb43
fix: update dependencies, fix compilation issues
pulsastrix Jun 15, 2024
c3fd6ce
feat: expand on openssl sign impl, add signature verification
pulsastrix Jun 16, 2024
4cb4fe5
test(token): separate tests for verification against self/examples
pulsastrix Jun 17, 2024
a522f50
feat: add ECDSA with P-384 and P-521 curves, expand tests
pulsastrix Jun 20, 2024
be190b5
refactor: rewrite cipher backend interface
pulsastrix Jun 24, 2024
af651fd
test(cose): run COSE_Sign1 tests from cose-wg examples repo
pulsastrix Jun 28, 2024
55b2268
feat: allow providing the AAD per signature
pulsastrix Jun 29, 2024
f955ebf
fix: make all COSE sign tests pass
pulsastrix Jun 29, 2024
d9f460e
refactor: split up COSE stuff a bit more
pulsastrix Jun 29, 2024
e6d2e70
feat: add support for CoseEncrypt0 using backend
pulsastrix Jun 29, 2024
7d17dfc
test(cose): add tests for CoseEncrypt0
pulsastrix Jun 29, 2024
afddf27
fix: GitHub actions now pull submodules
pulsastrix Jun 29, 2024
e417306
feat: support for recursive CoseRecipient structures using backend
pulsastrix Jul 2, 2024
b5393c4
feat: add encryption of CoseRecipients
pulsastrix Jul 3, 2024
1d88bd0
refactor: separate tests for COSE structures
pulsastrix Jul 3, 2024
c3439c7
feat: cipher based enc-/decryption for CoseMac/CoseEncrypt
pulsastrix Jul 4, 2024
a036b4f
test: tests for CoseEncrypt enveloped and AES key wrap
pulsastrix Jul 5, 2024
bffa954
feat: support CoseMac0, tests for CoseMac and CoseMac0
pulsastrix Jul 6, 2024
85af40a
refactor: clean up COSE tests, apply lint fixes
pulsastrix Jul 9, 2024
d4326e4
refactor: fix non-documentation lints for cose module
pulsastrix Jul 9, 2024
3413cbe
tests: refactor and re-enable access token tests
pulsastrix Jul 14, 2024
ab47513
refactor: some more cleanup and lint fixes
pulsastrix Jul 14, 2024
f6824cc
refactor: apply review suggestions and some more lints
pulsastrix Jul 14, 2024
bb93edf
refactor: simplify, re-enable integration test, remaining #13 review …
pulsastrix Jul 15, 2024
3009a78
doc: large batch of documentation for most stuff, minor fixes
pulsastrix Jul 16, 2024
90f3e78
refactor: rewrite AAD and key providers, simplify API
pulsastrix Jul 19, 2024
50cf803
refactor: more descriptive error for nested recipient decrypters
pulsastrix Jul 23, 2024
d8cd1e2
refactor: code cleanup of COSE token cryptography
pulsastrix Jul 23, 2024
9b5f2be
docs: update documentation regarding COSE cryptography
pulsastrix Jul 24, 2024
696c62d
docs: fix and simplify documentation links
pulsastrix Jul 24, 2024
e3e65eb
chore: apply suggestions from code review (#13)
pulsastrix Jul 31, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
68 changes: 36 additions & 32 deletions .github/workflows/check.yml
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ jobs:
name: Check
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- uses: actions/checkout@v4
- uses: actions-rs/toolchain@v1
with:
profile: minimal
Expand All @@ -22,25 +22,27 @@ jobs:
command: check

check_nostd:
name: Check (no_std)
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- uses: actions-rs/toolchain@v1
with:
profile: minimal
toolchain: stable
override: true
- uses: actions-rs/cargo@v1
with:
command: check
args: --no-default-features
name: Check (no_std)
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions-rs/toolchain@v1
with:
profile: minimal
toolchain: stable
override: true
- uses: actions-rs/cargo@v1
with:
command: check
args: --no-default-features

test:
name: Test Suite
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- uses: actions/checkout@v4
with:
submodules: true
- uses: actions-rs/toolchain@v1
with:
profile: minimal
Expand All @@ -51,25 +53,25 @@ jobs:
command: test

test_nostd:
name: Test Suite (no_std)
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- uses: actions-rs/toolchain@v1
with:
profile: minimal
toolchain: stable
override: true
- uses: actions-rs/cargo@v1
with:
command: test
args: --no-default-features
name: Test Suite (no_std)
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions-rs/toolchain@v1
with:
profile: minimal
toolchain: stable
override: true
- uses: actions-rs/cargo@v1
with:
command: test
args: --no-default-features --features openssl

fmt:
name: Rustfmt
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- uses: actions/checkout@v4
- uses: actions-rs/toolchain@v1
with:
profile: minimal
Expand All @@ -84,7 +86,7 @@ jobs:
clippy_check:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- uses: actions/checkout@v4
- run: rustup component add clippy
- uses: actions-rs/clippy-check@v1
with:
Expand All @@ -94,7 +96,9 @@ jobs:
test_coverage:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v1
- uses: actions/checkout@v4
with:
submodules: true
- uses: actions-rs/toolchain@v1
with:
toolchain: nightly
Expand All @@ -116,4 +120,4 @@ jobs:
uses: coverallsapp/github-action@master
with:
github-token: ${{ secrets.GITHUB_TOKEN }}
path-to-lcov: ${{ steps.coverage.outputs.report }}
path-to-lcov: ${{ steps.coverage.outputs.report }}
3 changes: 3 additions & 0 deletions .gitmodules
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
[submodule "tests/cose_examples"]
path = tests/cose_examples
url = https://github.com/cose-wg/Examples.git
86 changes: 69 additions & 17 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,23 +5,73 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).

## [Unreleased]

This release reworks the access token API and fully implements extensions to the COSE structures provided by `coset`
that allow using pre-defined cryptographic backends.
This way, it is no longer required for applications to implement cryptographic operations and logic to verify that
COSE structures match the specification.

> [!NOTE]
> The long-term plan is to integrate these extensions into `coset` at some point (assuming that they would be
> interested in this code). This might come with minor API adjustments (e.g. by removing some parameters to builder
> methods that already have their own builder method, but whose fields we can't access from outside of `coset`), but the
> basic design of this module should now be quite stable.
> Applications can expect to only have to make minor changes in calls to these operations for the foreseeable future.

### Added

- An entire new submodule `token/cose` that is responsible for easier handling of creation and verification of COSE
structures.
Instead of manually defining glue code to cryptographic libraries for each call and checking whether the COSE
structure is specification-compliant, this module takes care of most of the validation and leaves the basic
cryptographic operations to reusable predefined cryptographic backends.
- `CoseEncryptExt`/`CoseEncrypt0Ext`/`CoseSignExt`/`CoseSign1Ext`/`CoseMacExt`/`CoseMac0Ext`: Extension traits for
the corresponding `coset` types that allow for easy verification of those COSE structures.
- `CoseEncryptBuilderExt`/`CoseEncrypt0BuilderExt`/`CoseSignBuilderExt`/`CoseSign1BuilderExt`/`CoseMacBuilderExt`/
`CoseMac0BuilderExt`: Extension traits for the corresponding `coset` types that allow for easy creation of those
COSE structures.
- `CoseRecipientExt`/`CoseRecipientBuilderExt`: Extensions for creating and decrypting COSE recipients, which may
be used in `CoseEncrypt` and `CoseMac` structures to encode data for multiple recipients at once.
- A cryptographic backend based on the `openssl` crate (a `RustCrypto` backend will be following soon, see #20).

### Changed

- `encrypt_access_token_multiple`/`decrypt_access_token_multiple`: Parameters have been adjusted to use the new COSE
extensions
- `sign_access_token_multiple` / `verify_access_token_multiple`: Parameters have been adjusted to use the new COSE
extensions
- `encrypt_access_token`/`decrypt_access_token`: Parameters have been adjusted to use the new COSE extensions
- `sign_access_token` / `verify_access_token`: Parameters have been adjusted to use the new COSE extensions
- `CoseCipher`/`CoseEncryptCipher`/`CoseSignCipher`/`CoseMacCipher`: Renamed to `CryptoBackend`/`EncryptCryptoBackend`/
`SignCryptoBackend`/`MacCryptoBackend` and fully reworked. These traits now only need to implement the basic
cryptographic operations, almost everything else (validation of header parameters, identifying suitable keys, ...) is
now handled by the `coset` extensions.

### Removed

- `MultipleEncryptCipher`/`MultipleSignCipher`: No longer required as the cryptographic backends no longer have to
handle those differently. This is taken care of by the `token/cose` module now.

## [0.4.0] --- 2023-03-27

This release mainly adds support for multiple token recipients, deals with the newly released RFCs,
and fixes `no_std` support.
and fixes `no_std` support.
Note that the cipher interfaces have been refactored in a major way.

### Added

- The `CoapOscore` profile has been added as an `AceProfile`.
- Support for multiple token recipients has been added. Specifically, the following new methods have been added:
- `encrypt_access_token_multiple` / `decrypt_access_token_multiple`: Creates a new access token encoded as a
`CoseEncrypt` rather than a `CoseEncrypt0`. The user passes in a vector of keys on encryption, these will then be
used as Key Encryption Keys. The Content Encryption Key is generated by the `MultipleEncryptCipher` required by
the function. On decryption, the correct recipient structure will be identified by the key ID of the passed-in key.
- `sign_access_token_multiple` / `decrypt_access_token_multiple`: Creates a new access token encoded as a `CoseSign`
rather than a `CoseSign1`. The user passes in a vector of keys when signing, and a recipient will be created
for each key. When verifying, the correct recipient structure will be identified by the key ID of the passed-in key.
- `encrypt_access_token_multiple` / `decrypt_access_token_multiple`: Creates a new access token encoded as a
`CoseEncrypt` rather than a `CoseEncrypt0`. The user passes in a vector of keys on encryption, these will then be
used as Key Encryption Keys. The Content Encryption Key is generated by the `MultipleEncryptCipher` required by
the function. On decryption, the correct recipient structure will be identified by the key ID of the passed-in
key.
- `sign_access_token_multiple` / `decrypt_access_token_multiple`: Creates a new access token encoded as a `CoseSign`
rather than a `CoseSign1`. The user passes in a vector of keys when signing, and a recipient will be created
for each key. When verifying, the correct recipient structure will be identified by the key ID of the passed-in
key.

### Changed

Expand Down Expand Up @@ -64,11 +114,11 @@ with `AifRestMethod` (using [`enumflags2`]).
`AifRestMethodSet` has been added too.
The reason for this is that this makes it possible to declare
*single* REST methods in a type-safe manner.
- Note that any existing usages of `AifRestMethodSet` now need to
be replaced with the new corresponding API calls.
- Variant names are now using `PascalCase` instead of `UPPER_CASE`.
- Use the type `AifRestMethod` for a single REST method and
`AifRestMethodSet` for a set of REST methods.
- Note that any existing usages of `AifRestMethodSet` now need to
be replaced with the new corresponding API calls.
- Variant names are now using `PascalCase` instead of `UPPER_CASE`.
- Use the type `AifRestMethod` for a single REST method and
`AifRestMethodSet` for a set of REST methods.
- The `derive_builder` dependency has been updated to 0.11.2.

### Fixed
Expand All @@ -84,13 +134,14 @@ This release focuses on introducing [AIF] and [libdcaf]-support.
- Support for scopes using the
[Authorization Information Format (AIF) for ACE](https://www.rfc-editor.org/rfc/rfc9237.html).
For this purpose, the following types have been added:
- `AifEncodedScope`, representing an AIF-encoded scope (surprise)
- `AifEncodedScopeElement`, a single element in an AIF-encoded scope
- `AifRestMethodSet`, encoding a set of REST methods
- Support for scopes used by the [libdcaf] implementation
- `AifEncodedScope`, representing an AIF-encoded scope (surprise)
- `AifEncodedScopeElement`, a single element in an AIF-encoded scope
- `AifRestMethodSet`, encoding a set of REST methods
- Support for scopes used by the [libdcaf] implementation
(a variant of AIF-encoded scopes).

### Fixed

- Binary-encoded scopes are now properly serialized.
- Some incorrect documentation regarding scopes has been corrected.

Expand All @@ -101,6 +152,7 @@ For more extensive documentation, consult the
[crate-level documentation](https://docs.rs/dcaf).

### Added

- CBOR de-/serializable model of the ACE-OAuth framework has been added:
- Binary- and text-encoded scopes
- Access token requests and responses
Expand Down
24 changes: 15 additions & 9 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -4,31 +4,37 @@ description = "An implementation of the ACE-OAuth framework"
version = "0.4.0"
edition = "2021"
authors = ["Falko Galperin <[email protected]>"]
rust-version = "1.58"
rust-version = "1.62"
license = "MIT OR Apache-2.0"
keywords = ["no_std", "framework", "oauth", "ace"]
categories = ["authentication", "data-structures", "embedded", "encoding", "no-std"]
repository = "https://github.com/namib-project/dcaf-rs"
exclude = [
".gitlab/*", ".gitlab-ci.yml"
".gitlab/*", ".gitlab-ci.yml", ".github/*"
]

[features]
default = ["std"]
default = ["std", "openssl"]
falko17 marked this conversation as resolved.
Show resolved Hide resolved
std = ["serde/std", "ciborium/std", "serde_bytes/std", "erased-serde/std", "derive_builder/std"]

[dependencies]
serde = { version = "1.0", default-features = false, features = ["derive"] }
ciborium = { version = "^0.2", default-features = false }
ciborium-io = { version = "^0.2", default-features = false }
coset = { version = "^0.3", default-features = false }
coset = { version = "^0.3", default-features = false, git = "https://github.com/namib-project/coset.git", branch = "fix_zero_length_map" }#, path = "../coset" }
falko17 marked this conversation as resolved.
Show resolved Hide resolved
serde_bytes = { version = "^0.11", default-features = false, features = ["alloc"] }
erased-serde = { version = "^0.3", default-features = false, features = ["alloc"] }
derive_builder = { version = "^0.12", default-features = false }
strum = { version = "^0.24", default-features = false, features = ["derive"] }
strum_macros = { version = "^0.24", default-features = false }
erased-serde = { version = "0.4.5", default-features = false, features = ["alloc"] }
derive_builder = { version = "0.20", default-features = false, features = ["alloc"] }
strum = { version = "0.26", default-features = false, features = ["derive"] }
strum_macros = { version = "0.26", default-features = false }
falko17 marked this conversation as resolved.
Show resolved Hide resolved
enumflags2 = { version = "^0.7", default-features = false }
rand = { version = "^0.8", default-features = false }
openssl = { version = "^0.10", optional = true }
lazy_static = "1.4.0"

[dev-dependencies]
hex = { version = "^0.4" }
hex = { version = "^0.4", features = ["serde"] }
base64 = "0.22.1"
rstest = "0.21.0"
serde_json = "1.0.118"
rand = { version = "^0.8", default-features = false, features = ["std_rng", "std"] }
Loading
Loading