From 5709d8d6943676763ce631a09ab65c293520be11 Mon Sep 17 00:00:00 2001 From: Aidan Garske Date: Tue, 6 Oct 2026 12:01:41 -0700 Subject: [PATCH] Build the wolfCOSE manual with the shared documentation tooling --- .github/workflows/docs-site.yml | 73 +++++++++ .github/workflows/misra-2023.yml | 3 +- .github/workflows/publish-docs-image.yml | 42 ++++++ .github/workflows/wiki-sync.yml | 37 ----- .gitignore | 3 + ChangeLog.md | 2 +- IDE/STM32Cube/README.md | 2 +- README.md | 40 ++--- docker/docs/Dockerfile | 15 ++ docker/docs/requirements.txt | 1 + docs/API-Reference.md | 10 +- docs/Algorithms.md | 8 +- docs/Footprint.md | 8 +- docs/Getting-Started.md | 10 +- docs/Home.md | 69 --------- docs/MISRA-Compliance.md | 2 +- docs/Macros.md | 16 +- docs/Message-Types.md | 10 +- docs/PSA-EAT.md | 2 +- docs/Project-Structure.md | 8 +- docs/README.md | 16 -- docs/Release-Notes.md | 16 +- docs/Testing.md | 16 +- docs/_Sidebar.md | 16 -- docs/assets/logo.png | Bin 0 -> 12440 bytes docs/assets/skin.css | 25 ++++ docs/dev/DOCS-BUILD.md | 68 +++++++++ docs/index.md | 84 +++++++++++ mkdocs.yml | 63 ++++++++ tools/check-docs-no-internal-links.sh | 49 ++++++ tools/docs-manual/Makefile | 15 ++ tools/docs-manual/documentation-rev | 1 + tools/docs_manual.py | 181 +++++++++++++++++++++++ 33 files changed, 698 insertions(+), 213 deletions(-) create mode 100644 .github/workflows/docs-site.yml create mode 100644 .github/workflows/publish-docs-image.yml delete mode 100644 .github/workflows/wiki-sync.yml create mode 100644 docker/docs/Dockerfile create mode 100644 docker/docs/requirements.txt delete mode 100644 docs/Home.md delete mode 100644 docs/README.md delete mode 100644 docs/_Sidebar.md create mode 100644 docs/assets/logo.png create mode 100644 docs/assets/skin.css create mode 100644 docs/dev/DOCS-BUILD.md create mode 100644 docs/index.md create mode 100644 mkdocs.yml create mode 100755 tools/check-docs-no-internal-links.sh create mode 100644 tools/docs-manual/Makefile create mode 100644 tools/docs-manual/documentation-rev create mode 100755 tools/docs_manual.py diff --git a/.github/workflows/docs-site.yml b/.github/workflows/docs-site.yml new file mode 100644 index 00000000..d212766f --- /dev/null +++ b/.github/workflows/docs-site.yml @@ -0,0 +1,73 @@ +name: Build manual with documentation tooling + +on: + pull_request: + paths: + - 'docs/**' + - 'mkdocs.yml' + - 'tools/docs_manual.py' + - 'tools/docs-manual/**' + - 'docker/docs/**' + - '.github/workflows/docs-site.yml' + push: + branches: [main] + paths: + - 'docs/**' + - 'mkdocs.yml' + - 'tools/docs_manual.py' + - 'tools/docs-manual/**' + - 'docker/docs/**' + - '.github/workflows/docs-site.yml' + workflow_dispatch: + +permissions: + contents: read + packages: read + +jobs: + build: + runs-on: ubuntu-24.04 + timeout-minutes: 60 + steps: + - uses: actions/checkout@v4 + - name: Select documentation revision + id: documentation + run: echo "sha=$(cat tools/docs-manual/documentation-rev)" >> "$GITHUB_OUTPUT" + - uses: actions/checkout@v4 + with: + repository: wolfSSL/documentation + ref: ${{ steps.documentation.outputs.sha }} + path: build/documentation + submodules: recursive + persist-credentials: false + - uses: docker/login-action@v3 + with: + registry: ghcr.io + username: ${{ github.actor }} + password: ${{ secrets.GITHUB_TOKEN }} + - name: Pull documentation builder + run: | + set -euo pipefail + image_sha=$(sha256sum docker/docs/Dockerfile docker/docs/requirements.txt | sha256sum | cut -c1-16) + image="ghcr.io/wolfssl/wolfcose-docs:sha-$image_sha" + if ! docker pull "$image"; then + docker build --pull -t "$image" docker/docs + fi + echo "DOCS_IMAGE=$image" >> "$GITHUB_ENV" + - name: Build and validate HTML and PDF + run: | + tools/check-docs-no-internal-links.sh + docker run --rm --user "$(id -u):$(id -g)" --env HOME=/tmp \ + --mount "type=bind,source=$GITHUB_WORKSPACE,target=/work/wolfCOSE" \ + --workdir /work/wolfCOSE "$DOCS_IMAGE" \ + sh -c 'python3 tools/docs_manual.py build --documentation-root /work/wolfCOSE/build/documentation --source-root /work/wolfCOSE --target all && cd build/documentation/wolfCOSE && mkdocs build --strict -f mkdocs.yml' + test -s build/documentation/wolfCOSE/html/index.html + test -s build/documentation/wolfCOSE/wolfCOSE-Manual.pdf + - uses: actions/upload-artifact@v4 + with: + name: wolfcose-manual + path: | + build/documentation/wolfCOSE/html/ + build/documentation/wolfCOSE/wolfCOSE-Manual.pdf + if-no-files-found: error + retention-days: 14 diff --git a/.github/workflows/misra-2023.yml b/.github/workflows/misra-2023.yml index a1772a47..32c4dea7 100644 --- a/.github/workflows/misra-2023.yml +++ b/.github/workflows/misra-2023.yml @@ -206,8 +206,7 @@ jobs: - name: Run clang-tidy run: | export WOLFSSL_DIR=$HOME/wolfssl-install - # Deviations (documented at - # https://github.com/wolfSSL/wolfCOSE/wiki/MISRA-Compliance): + # Deviations (documented in docs/MISRA-Compliance.md): # # -bugprone-branch-clone: Different COSE algorithms intentionally # map to the same wolfCrypt value (e.g. ES512 and EdDSA both diff --git a/.github/workflows/publish-docs-image.yml b/.github/workflows/publish-docs-image.yml new file mode 100644 index 00000000..51b7907c --- /dev/null +++ b/.github/workflows/publish-docs-image.yml @@ -0,0 +1,42 @@ +name: Publish documentation image + +on: + push: + branches: [main] + paths: + - 'docker/docs/**' + - '.github/workflows/publish-docs-image.yml' + workflow_dispatch: + +permissions: + contents: read + packages: write + +concurrency: + group: publish-wolfcose-docs-image + cancel-in-progress: false + +jobs: + publish: + if: github.repository == 'wolfSSL/wolfCOSE' + runs-on: ubuntu-24.04 + timeout-minutes: 30 + steps: + - uses: actions/checkout@v4 + - name: Select image tag + id: image + run: | + image_sha=$(sha256sum docker/docs/Dockerfile docker/docs/requirements.txt | sha256sum | cut -c1-16) + echo "tag=ghcr.io/wolfssl/wolfcose-docs:sha-$image_sha" >> "$GITHUB_OUTPUT" + - uses: docker/setup-buildx-action@v3 + - uses: docker/login-action@v3 + with: + registry: ghcr.io + username: ${{ github.actor }} + password: ${{ secrets.GITHUB_TOKEN }} + - uses: docker/build-push-action@v6 + with: + context: docker/docs + file: docker/docs/Dockerfile + push: true + tags: ${{ steps.image.outputs.tag }} diff --git a/.github/workflows/wiki-sync.yml b/.github/workflows/wiki-sync.yml deleted file mode 100644 index 7785d7d5..00000000 --- a/.github/workflows/wiki-sync.yml +++ /dev/null @@ -1,37 +0,0 @@ -name: Sync docs to wiki - -# The wiki is a generated mirror of docs/. Edit docs/ via pull requests; -# this publishes them to the GitHub wiki on every merge to main. -on: - push: - branches: [main] - paths: ['docs/**'] - workflow_dispatch: - -permissions: - contents: write - -concurrency: - group: wiki-sync - cancel-in-progress: true - -defaults: - run: - shell: bash -e {0} - -jobs: - sync: - runs-on: ubuntu-latest - container: - image: ghcr.io/wolfssl/wolfcose-ci@sha256:c073c7afb4cd3f296b8c1a305db2f718530b7a8aca899482629aee3a5cf8bfbc - steps: - - uses: actions/checkout@v4 - - - name: Trust workspace - if: runner.os == 'Linux' - run: git config --global --add safe.directory "$GITHUB_WORKSPACE" - - - name: Publish docs/ to wiki - uses: Andrew-Chen-Wang/github-wiki-action@50650fccf3a10f741995523cf9708c53cec8912a # v4 - with: - path: docs/ diff --git a/.gitignore b/.gitignore index 62acc949..7ca05baa 100644 --- a/.gitignore +++ b/.gitignore @@ -8,6 +8,9 @@ experimental-check.err *.dSYM/ .wolfcose-build-config +# Docs manual build output (see DOCS-BUILD.md) +/build/ + # Binaries tests/test_wolfcose tests/test_wolfcose_eat_psa diff --git a/ChangeLog.md b/ChangeLog.md index 1f7e79b8..8cea0501 100644 --- a/ChangeLog.md +++ b/ChangeLog.md @@ -187,7 +187,7 @@ MAC, and key distribution, and standardized post-quantum ML-DSA signatures * Minimal footprint: an ES256 `COSE_Sign1` build is ~5.1 KB verify-only and ~6.8 KB sign + verify for the wolfCOSE COSE + CBOR engine; see the - [Footprint](https://github.com/wolfSSL/wolfCOSE/wiki/Footprint) page for + [Footprint](https://www.wolfssl.com/documentation/manuals/wolfcose/Footprint.html) page for total-flash numbers including wolfCrypt. * MISRA C:2012 and C:2023 checked. * API hardening: `COSE_Encrypt` and `wc_CoseMac_Create` direct mode now require diff --git a/IDE/STM32Cube/README.md b/IDE/STM32Cube/README.md index db20529a..d3738119 100644 --- a/IDE/STM32Cube/README.md +++ b/IDE/STM32Cube/README.md @@ -41,5 +41,5 @@ wolfCOSE is configured through the wolfSSL `user_settings.h` (included before wolfCrypt features (`HAVE_ECC`, `WOLFSSL_SHA384/512`, `WOLFSSL_HAVE_MLDSA`). See the wolfCOSE `examples/` for sign1, mac0, and encrypt0 usage, and the -[STM32Cube wiki page](https://github.com/wolfSSL/wolfCOSE/wiki/STM32Cube) for +[STM32Cube manual page](https://www.wolfssl.com/documentation/manuals/wolfcose/STM32Cube.html) for the full walkthrough including a ready to run NUCLEO-H563ZI project. diff --git a/README.md b/README.md index 5b811f9d..e7292cd6 100644 --- a/README.md +++ b/README.md @@ -23,12 +23,12 @@ wolfCOSE is a lightweight and fast C library implementing core CBOR and COSE sta * **Post-Quantum Cryptography:** * ML-DSA (FIPS 204 / RFC 9964) at all security levels. * HSS/LMS stateful hash-based signing (RFC 8778 / CNSA 2.0). -* **Fast Performance:** On an Intel i9-11950H, end-to-end `COSE_Sign1` reaches 66,538 sign/s and 26,437 verify/s with ES256, and 21,986 sign/s and 53,686 verify/s with ML-DSA-44. See the [performance and footprint details](https://github.com/wolfSSL/wolfCOSE/wiki/Footprint) and [wolfCOSE vs. The Field](https://www.wolfssl.com/wolfcose-vs-the-field-the-smallest-and-fastest-cose-library-now-with-post-quantum-ml-dsa-at-the-same-cost/). +* **Fast Performance:** On an Intel i9-11950H, end-to-end `COSE_Sign1` reaches 66,538 sign/s and 26,437 verify/s with ES256, and 21,986 sign/s and 53,686 verify/s with ML-DSA-44. See the [performance and footprint details](https://www.wolfssl.com/documentation/manuals/wolfcose/Footprint.html) and [wolfCOSE vs. The Field](https://www.wolfssl.com/wolfcose-vs-the-field-the-smallest-and-fastest-cose-library-now-with-post-quantum-ml-dsa-at-the-same-cost/). * **PSA Attestation:** EAT / PSA Token issuance and verification with delegated HSM signing support. * **41 Cryptographic Algorithms:** Broad algorithm coverage across signing, encryption, MAC, and key distribution. * **Embedded-First Design:** Zero dynamic memory allocation (no heap, zero `.data`/`.bss`). Operates on caller-supplied buffers with bounded stack usage. * **FIPS 140-3 Path:** Uses wolfCrypt (FIPS Certificate #4718) as its sole cryptographic dependency. -* **STM32 Integrated:** Drop-in STM32Cube pack (`I-CUBE-wolfCOSE`) available for STM32CubeMX / IDE ([Details](https://github.com/wolfSSL/wolfCOSE/wiki/STM32Cube)). +* **STM32 Integrated:** Drop-in STM32Cube pack (`I-CUBE-wolfCOSE`) available for STM32CubeMX / IDE ([Details](https://www.wolfssl.com/documentation/manuals/wolfcose/STM32Cube.html)). ## Supported Algorithms @@ -71,7 +71,7 @@ the corresponding `wc_Cose_VerifyCounterSignature*()` API. wolfCOSE requires [wolfSSL](https://www.wolfssl.com/) as its crypto backend. **Minimum supported version: v5.8.0-stable**. Some optional algorithms require -newer releases; see [Getting Started](docs/Getting-Started.md#prerequisites) for +newer releases; see [Getting Started](https://www.wolfssl.com/documentation/manuals/wolfcose/Getting-Started.html#prerequisites) for feature-specific dependency floors and build instructions. HSS/LMS (RFC 8778) requires v5.9.2-stable or later. @@ -104,7 +104,7 @@ stack and disable the algorithms a Sign1 + Encrypt0 build never uses: --disable-errorstrings ``` -See [Tuning for Size](docs/Macros.md#tuning-for-size) and [Tuning for Speed](docs/Macros.md#tuning-for-speed) +See [Tuning for Size](https://www.wolfssl.com/documentation/manuals/wolfcose/Macros.html#tuning-for-size) and [Tuning for Speed](https://www.wolfssl.com/documentation/manuals/wolfcose/Macros.html#tuning-for-speed) for squeezing wolfCOSE and wolfCrypt further on MCUs. ### Minimal Build (Post-Quantum / ML-DSA only) @@ -213,19 +213,25 @@ make coverage-force-failure # Include crypto failure path testing ## Documentation -Full documentation is available in the [Wiki](https://github.com/wolfSSL/wolfCOSE/wiki): - -- [Getting Started](https://github.com/wolfSSL/wolfCOSE/wiki/Getting-Started): Build instructions and first steps -- [Message Types](https://github.com/wolfSSL/wolfCOSE/wiki/Message-Types): All six RFC 9052 messages (Sign1, Sign, Encrypt0, Encrypt, Mac0, Mac) and RFC 9338 countersignatures with code samples -- [Algorithms](https://github.com/wolfSSL/wolfCOSE/wiki/Algorithms): Complete list of 41 supported algorithms with COSE IDs -- [API Reference](https://github.com/wolfSSL/wolfCOSE/wiki/API-Reference): Function signatures, data structures, error codes -- [Macros](https://github.com/wolfSSL/wolfCOSE/wiki/Macros): Compile-time configuration, size tuning, and ECDSA nonce policy -- [PSA-EAT](https://github.com/wolfSSL/wolfCOSE/wiki/PSA-EAT): RFC 9783 PSA token profiles, APIs, macros, and security guidance -- [Footprint](https://github.com/wolfSSL/wolfCOSE/wiki/Footprint): Size and speed numbers, desktop and on-device -- [Testing](https://github.com/wolfSSL/wolfCOSE/wiki/Testing): Test infrastructure, coverage, and failure injection -- [MISRA Compliance](https://github.com/wolfSSL/wolfCOSE/wiki/MISRA-Compliance): MISRA C:2012 and C:2023 compliance status and deviation rationale -- [Project Structure](https://github.com/wolfSSL/wolfCOSE/wiki/Project-Structure): Source file layout -- [STM32Cube](https://github.com/wolfSSL/wolfCOSE/wiki/STM32Cube): Install and run wolfCOSE as an STM32Cube pack on device +The official wolfCOSE manual is published at +[wolfssl.com/documentation/manuals/wolfcose](https://www.wolfssl.com/documentation/manuals/wolfcose/index.html): + +- [Getting Started](https://www.wolfssl.com/documentation/manuals/wolfcose/Getting-Started.html): Build instructions and first steps +- [Message Types](https://www.wolfssl.com/documentation/manuals/wolfcose/Message-Types.html): All six RFC 9052 messages (Sign1, Sign, Encrypt0, Encrypt, Mac0, Mac) and RFC 9338 countersignatures with code samples +- [Algorithms](https://www.wolfssl.com/documentation/manuals/wolfcose/Algorithms.html): Complete list of 41 supported algorithms with COSE IDs +- [API Reference](https://www.wolfssl.com/documentation/manuals/wolfcose/API-Reference.html): Function signatures, data structures, error codes +- [Macros](https://www.wolfssl.com/documentation/manuals/wolfcose/Macros.html): Compile-time configuration, size tuning, and ECDSA nonce policy +- [PSA-EAT](https://www.wolfssl.com/documentation/manuals/wolfcose/PSA-EAT.html): RFC 9783 PSA token profiles, APIs, macros, and security guidance +- [Footprint](https://www.wolfssl.com/documentation/manuals/wolfcose/Footprint.html): Size and speed numbers, desktop and on-device +- [Testing](https://www.wolfssl.com/documentation/manuals/wolfcose/Testing.html): Test infrastructure, coverage, and failure injection +- [MISRA Compliance](https://www.wolfssl.com/documentation/manuals/wolfcose/MISRA-Compliance.html): MISRA C:2012 and C:2023 compliance status and deviation rationale +- [Project Structure](https://www.wolfssl.com/documentation/manuals/wolfcose/Project-Structure.html): Source file layout +- [STM32Cube](https://www.wolfssl.com/documentation/manuals/wolfcose/STM32Cube.html): Install and run wolfCOSE as an STM32Cube pack on device + +The manual sources live in [`docs/`](docs/); `mkdocs.yml` defines the navigation +and the shared [`wolfSSL/documentation`](https://github.com/wolfSSL/documentation) +tooling builds the HTML and PDF. See [docs/dev/DOCS-BUILD.md](docs/dev/DOCS-BUILD.md) +for local previews and how changes reach the website. ## Release Notes diff --git a/docker/docs/Dockerfile b/docker/docs/Dockerfile new file mode 100644 index 00000000..b5e806e1 --- /dev/null +++ b/docker/docs/Dockerfile @@ -0,0 +1,15 @@ +FROM python:3.12-slim-bookworm + +LABEL org.opencontainers.image.source="https://github.com/wolfSSL/wolfCOSE" + +RUN apt-get update \ + && apt-get install -y --no-install-recommends \ + bash git make patch perl librsvg2-bin \ + pandoc texlive-xetex texlive-latex-extra texlive-fonts-recommended \ + fonts-noto-core fonts-noto-mono lmodern \ + && rm -rf /var/lib/apt/lists/* + +COPY requirements.txt /tmp/requirements-docs.txt +RUN python -m pip install --no-cache-dir -r /tmp/requirements-docs.txt + +WORKDIR /work diff --git a/docker/docs/requirements.txt b/docker/docs/requirements.txt new file mode 100644 index 00000000..f2caded5 --- /dev/null +++ b/docker/docs/requirements.txt @@ -0,0 +1 @@ +mkdocs==1.6.1 diff --git a/docs/API-Reference.md b/docs/API-Reference.md index 3bf051f2..ba2acb59 100644 --- a/docs/API-Reference.md +++ b/docs/API-Reference.md @@ -1164,7 +1164,7 @@ pin the same algorithm. ## PSA/EAT API Available only when `WOLFCOSE_ENABLE_EAT_PSA` and the selected profile and -envelope gates are defined. Include ``. See [[PSA-EAT]] +envelope gates are defined. Include ``. See [PSA-EAT](PSA-EAT.md) for configuration and security requirements. ### wc_CoseEatPsaToken_Verify @@ -1415,7 +1415,7 @@ numeric `crit` is rejected. `wc_CoseKey_Decode()` and ## See Also -- [[Getting Started]]: Build instructions and examples -- [[Algorithms]]: Supported algorithms -- [[Macros]]: Compile-time configuration -- [[PSA-EAT]]: RFC 9783 PSA attestation support +- [Getting Started](Getting-Started.md): Build instructions and examples +- [Algorithms](Algorithms.md): Supported algorithms +- [Macros](Macros.md): Compile-time configuration +- [PSA-EAT](PSA-EAT.md): RFC 9783 PSA attestation support diff --git a/docs/Algorithms.md b/docs/Algorithms.md index 881be826..f4e39c5f 100644 --- a/docs/Algorithms.md +++ b/docs/Algorithms.md @@ -1,6 +1,6 @@ # Supported Algorithms -wolfCOSE supports 46 algorithms across signing, encryption, MAC, and key distribution. This page provides the complete list with COSE algorithm IDs and required wolfSSL compile-time guards. All algorithms are usable in both single-actor messages (Sign1/Encrypt0/Mac0) and multi-actor messages (Sign/Encrypt/Mac). See [[Message Types]] for details. +wolfCOSE supports 46 algorithms across signing, encryption, MAC, and key distribution. This page provides the complete list with COSE algorithm IDs and required wolfSSL compile-time guards. All algorithms are usable in both single-actor messages (Sign1/Encrypt0/Mac0) and multi-actor messages (Sign/Encrypt/Mac). See [Message Types](Message-Types.md) for details. ## COSE_Sign1 (Digital Signatures) @@ -224,6 +224,6 @@ Future algorithm support planned: ## See Also -- [[Getting Started]]: Build instructions and examples -- [[API Reference]]: Function documentation -- [[Macros]]: Compile-time configuration +- [Getting Started](Getting-Started.md): Build instructions and examples +- [API Reference](API-Reference.md): Function documentation +- [Macros](Macros.md): Compile-time configuration diff --git a/docs/Footprint.md b/docs/Footprint.md index 18d8057d..56710251 100644 --- a/docs/Footprint.md +++ b/docs/Footprint.md @@ -28,7 +28,7 @@ The verify-only profile is the common on-device case: a device verifies signed f ## Build-profile footprint -The lean profiles (see [[Macros]] → Build Profiles). *Glue* is the wolfCOSE engine alone; *total* adds the minimal wolfCrypt backend. +The lean profiles (see [Macros](Macros.md) -> Build Profiles). *Glue* is the wolfCOSE engine alone; *total* adds the minimal wolfCrypt backend. | Profile | Algorithm | wolfCOSE glue | Total + wolfCrypt | |---------|-----------|---------------|-------------------| @@ -78,6 +78,6 @@ Desktop: x86_64 Intel i9-11950H, GCC 14.2. ES256 was measured in June 2026 using ## See Also -- [[Macros]]: build profiles and configuration -- [[Testing]]: memory and stack-bound enforcement in CI -- [[Getting Started]]: building wolfCOSE +- [Macros](Macros.md): build profiles and configuration +- [Testing](Testing.md): memory and stack-bound enforcement in CI +- [Getting Started](Getting-Started.md): building wolfCOSE diff --git a/docs/Getting-Started.md b/docs/Getting-Started.md index 78e5e072..420db298 100644 --- a/docs/Getting-Started.md +++ b/docs/Getting-Started.md @@ -482,7 +482,7 @@ Related strictness that surprises integrators for the same reason: - Trailing bytes after the encoded object are rejected. `inSz` must be exactly the object length, not the capacity of the buffer holding it. Use - [`wc_CBOR_SkipItem()`](API-Reference.md#wc_cbor_skipitem) to carve out the + [`wc_CBOR_SkipItem()`](API-Reference.md#decoding-functions) to carve out the exact byte range of an embedded item. - Two-byte simple values below 32 are malformed, per RFC 8949. - All encountered CBOR text strings are validated as UTF-8. This also applies @@ -534,7 +534,7 @@ Per-function stack usage (from `-fstack-usage`, GCC, `-Os`, aarch64): ## Next Steps -- [[Algorithms]]: See all supported algorithms -- [[API Reference]]: Complete function documentation -- [[Macros]]: Configure compile-time options -- [[Testing]]: Run tests and measure coverage +- [Algorithms](Algorithms.md): See all supported algorithms +- [API Reference](API-Reference.md): Complete function documentation +- [Macros](Macros.md): Configure compile-time options +- [Testing](Testing.md): Run tests and measure coverage diff --git a/docs/Home.md b/docs/Home.md deleted file mode 100644 index 673a727b..00000000 --- a/docs/Home.md +++ /dev/null @@ -1,69 +0,0 @@ -# wolfCOSE Documentation - -Welcome to the wolfCOSE wiki. This is the complete documentation for wolfCOSE, a lightweight CBOR and COSE library for embedded systems. - -## What is wolfCOSE? - -wolfCOSE is a C library implementing: -- **CBOR** (RFC 8949): Concise Binary Object Representation -- **COSE** (RFC 9052/9053): CBOR Object Signing and Encryption, with the RFC 9864 fully-specified signature algorithms - -It uses [wolfSSL](https://www.wolfssl.com/) as the cryptographic backend and is designed for constrained IoT devices, FIPS-bounded deployments, and anywhere you need authenticated CBOR payloads in minimal RAM. - -## Key Features - -| Feature | Description | -|---------|-------------| -| Complete RFC 9052 | All six COSE message types — Sign1, Sign, Encrypt0, Encrypt, Mac0, Mac | -| Multi-signer / multi-recipient | Full `COSE_Sign`, `COSE_Encrypt`, and `COSE_Mac` support | -| Post-quantum signing | ML-DSA (FIPS 204) at all three security levels — first COSE library to ship native PQC | -| PSA attestation | Optional RFC 9783 EAT / PSA token verifier and issuer, including Sign1, Mac0, legacy consumption, and PSA/HSM delegated signing | -| Zero dynamic allocation | Heap-allocation-free, non-recursive; caller-provided buffers within a bounded, target-customizable stack ceiling — zero `.data`/`.bss` | -| Tiny footprint | 3.5–5.1 KB COSE engine, 5.1–6.8 KB with the built-in CBOR engine (verify-only → sign + verify); 26.2 KB → 34.6 KB total with wolfCrypt — ES256 `COSE_Sign1`, dead-code-eliminated | -| 41 algorithms | Signing, encryption, MAC, and key distribution — classical and post-quantum | -| FIPS 140-3 path | Sole crypto dependency is wolfCrypt FIPS Certificate #4718 | -| CNSA 2.0 ready | ML-DSA-44/65/87 for quantum-resistant signatures | -| MISRA-C:2023 | compliance striving, Single-exit pattern, no recursion, deviation-logged | - -## Documentation - -| Page | Description | -|------|-------------| -| [[Getting Started]] | Prerequisites, building, and quick start examples | -| [[Message Types]] | All six RFC 9052 messages (Sign1/Sign, Encrypt0/Encrypt, Mac0/Mac) with code samples | -| [[Algorithms]] | Complete list of supported algorithms with COSE IDs | -| [[API Reference]] | Full API documentation for all functions | -| [[Macros]] | Configuration macros and compile-time options | -| [[Experimental]] | Draft feature status, supported scope, and graduation plan | -| [[PSA-EAT]] | RFC 9783 PSA attestation profiles, APIs, and integration guidance | -| [[Footprint]] | Size and speed numbers, desktop and on-device | -| [[Testing]] | Unit tests, coverage, and failure injection | -| [[Project Structure]] | Source code layout and file descriptions | -| [[STM32Cube]] | Install and run wolfCOSE as an STM32Cube pack on device | -| [[Release Notes]] | Per-version changelog and release highlights | - -## Supported Message Types - -wolfCOSE implements all six COSE message types from RFC 9052: - -| Message Type | Tag | Description | -|--------------|-----|-------------| -| COSE_Sign1 | 18 | Single signer digital signature | -| COSE_Sign | 98 | Multiple signers | -| COSE_Encrypt0 | 16 | Symmetric encryption (single key) | -| COSE_Encrypt | 96 | Multi-recipient encryption | -| COSE_Mac0 | 17 | Symmetric MAC (single key) | -| COSE_Mac | 97 | Multi-recipient MAC | - -## Quick Links - -- [GitHub Repository](https://github.com/wolfSSL/wolfCOSE) -- [wolfSSL Website](https://www.wolfssl.com/) -- [RFC 8949 (CBOR)](https://www.rfc-editor.org/rfc/rfc8949) -- [RFC 9052 (COSE Structures)](https://www.rfc-editor.org/rfc/rfc9052) -- [RFC 9053 (COSE Algorithms)](https://www.rfc-editor.org/rfc/rfc9053) -- [RFC 9864 (Fully-Specified Algorithms)](https://www.rfc-editor.org/rfc/rfc9864) - -## License - -wolfCOSE is free software licensed under GPLv3. For commercial licensing and support, contact [wolfSSL](https://www.wolfssl.com/contact/). diff --git a/docs/MISRA-Compliance.md b/docs/MISRA-Compliance.md index 85d42963..a6be1c98 100644 --- a/docs/MISRA-Compliance.md +++ b/docs/MISRA-Compliance.md @@ -15,7 +15,7 @@ Verified via cppcheck's MISRA addon (`--addon=misra`) with all wolfCOSE algorith **Workflow**: `.github/workflows/misra-2012.yml` -All wolfCOSE and wolfSSL feature macros are explicitly defined so cppcheck checks the full code path rather than enumerating wolfSSL's hundreds of platform `#ifdef` configurations. This includes all four default-off experimental COSE-HPKE operation gates, `WOLFCOSE_EXPERIMENTAL`, wolfSSL HPKE support, and `WOLFCOSE_ENABLE_DEPRECATED_ALGS`, so draft HPKE code and opt-in RFC 9053 algorithm paths are analyzed rather than silently excluded. See [[Macros]] for the complete list. +All wolfCOSE and wolfSSL feature macros are explicitly defined so cppcheck checks the full code path rather than enumerating wolfSSL's hundreds of platform `#ifdef` configurations. This includes all four default-off experimental COSE-HPKE operation gates, `WOLFCOSE_EXPERIMENTAL`, wolfSSL HPKE support, and `WOLFCOSE_ENABLE_DEPRECATED_ALGS`, so draft HPKE code and opt-in RFC 9053 algorithm paths are analyzed rather than silently excluded. See [Macros](Macros.md) for the complete list. ### MISRA C:2023 diff --git a/docs/Macros.md b/docs/Macros.md index 7cf68cf3..5a287385 100644 --- a/docs/Macros.md +++ b/docs/Macros.md @@ -122,7 +122,7 @@ and one RFC 9783 Sign1 or Mac0 creation path can issue a correctly labelled `#tfm` token. A selective current-profile verifier still rejects `#tfm` with `WOLFCOSE_E_EAT_PSA_PROFILE` and must not advertise full receiver conformance. -See [[PSA-EAT]] for examples, profile boundaries, and security guidance. +See [PSA-EAT](PSA-EAT.md) for examples, profile boundaries, and security guidance. ## Algorithm Gates @@ -487,7 +487,7 @@ wolfSSL release. ### `WOLFCOSE_MIN_BUFFERS` -One define that trims the caller working set to the minimum that still fits the enabled algorithms. It tightens the CBOR parsing limits (`WOLFCOSE_CBOR_MAX_DEPTH` 8→6, `WOLFCOSE_MAX_MAP_ITEMS` 16→8) and keeps the algorithm-driven signature/scratch floors, which track the largest enabled signature algorithm: +One define that trims the caller working set to the minimum that still fits the enabled algorithms. It tightens the CBOR parsing limits (`WOLFCOSE_CBOR_MAX_DEPTH` 8->6, `WOLFCOSE_MAX_MAP_ITEMS` 16->8) and keeps the algorithm-driven signature/scratch floors, which track the largest enabled signature algorithm: | Enabled signature algorithm | `WOLFCOSE_MAX_SIG_SZ` | `WOLFCOSE_MAX_SCRATCH_SZ` | |---|---|---| @@ -504,7 +504,7 @@ Because the floor follows the algorithm, `WOLFCOSE_MIN_BUFFERS` stays valid with ## Tuning for Size -Four levers, smallest impact last. See the [[Footprint]] page for the resulting numbers. +Four levers, smallest impact last. See the [Footprint](Footprint.md) page for the resulting numbers. 1. **Pick a build profile.** `WOLFCOSE_LEAN` is the lean ES256 core (6.8 KB glue); `WOLFCOSE_LEAN_VERIFY` is verify-only (5.1 KB); the ML-DSA profiles are post-quantum (see [Build Profiles](#build-profiles)). One define selects a curated gate set. 2. **Drop individual features** with `WOLFCOSE_NO_` (e.g. `WOLFCOSE_NO_ENCRYPT0`, `WOLFCOSE_NO_SIGN`, `WOLFCOSE_NO_RECIPIENTS`), or in a lean build add only what you need with `WOLFCOSE_ENABLE_`. @@ -535,7 +535,7 @@ Convenience macros that select a curated set of feature gates for a common deplo ### Footprint -What each profile costs (code + rodata, ES256/ML-DSA-44 `COSE_Sign1`, built from source with dead-code elimination). *Glue* is the wolfCOSE COSE + CBOR engine alone; *total* adds the minimal wolfCrypt backend. Full cross-library and on-device numbers are on the [[Footprint]] page. +What each profile costs (code + rodata, ES256/ML-DSA-44 `COSE_Sign1`, built from source with dead-code elimination). *Glue* is the wolfCOSE COSE + CBOR engine alone; *total* adds the minimal wolfCrypt backend. Full cross-library and on-device numbers are on the [Footprint](Footprint.md) page. | Profile | Algorithm | wolfCOSE glue | Total + wolfCrypt | |---------|-----------|---------------|-------------------| @@ -544,7 +544,7 @@ What each profile costs (code + rodata, ES256/ML-DSA-44 `COSE_Sign1`, built from | `WOLFCOSE_LEAN_MLDSA` | ML-DSA-44 sign + verify | 6.6 KB | 35.8 KB | | `WOLFCOSE_LEAN_VERIFY_MLDSA` | ML-DSA-44 verify-only | 4.6 KB | 20.8 KB | -Post-quantum sign + verify is within ~1 KB of classical ES256 (35.8 vs 34.6 KB), and PQ verify-only is actually *smaller* than classical ES256 verify-only (20.8 vs 26.2 KB): ML-DSA skips the DER signature conversion ECDSA needs. Full numbers (desktop, on-device, and speed) are on the [[Footprint]] page. +Post-quantum sign + verify is within ~1 KB of classical ES256 (35.8 vs 34.6 KB), and PQ verify-only is actually *smaller* than classical ES256 verify-only (20.8 vs 26.2 KB): ML-DSA skips the DER signature conversion ECDSA needs. Full numbers (desktop, on-device, and speed) are on the [Footprint](Footprint.md) page. ### `WOLFCOSE_LEAN_VERIFY` — minimal verify-only @@ -681,6 +681,6 @@ Sub-gates within tests: ## See Also -- [[Getting Started]]: Build instructions -- [[Algorithms]]: Supported algorithms with guards -- [[Testing]]: Test configuration +- [Getting Started](Getting-Started.md): Build instructions +- [Algorithms](Algorithms.md): Supported algorithms with guards +- [Testing](Testing.md): Test configuration diff --git a/docs/Message-Types.md b/docs/Message-Types.md index 2772f062..fa8e1508 100644 --- a/docs/Message-Types.md +++ b/docs/Message-Types.md @@ -12,7 +12,7 @@ wolfCOSE implements the complete RFC 9052 message set — all six COSE structure | `COSE_Mac` | Sec. 6.1 | 97 | `wc_CoseMac_Create` / `wc_CoseMac_Verify` | | `COSE_Key` / `COSE_KeySet` | Sec. 7 | (none) | `wc_CoseKey_Encode` / `wc_CoseKey_Decode` | -Every message can be built attached or detached, with optional external AAD, and every algorithm in [[Algorithms]] is available to every message type that accepts it. +Every message can be built attached or detached, with optional external AAD, and every algorithm in [Algorithms](Algorithms.md) is available to every message type that accepts it. ## COSE_Sign1 — single-signer signature (RFC 9052 Sec. 4.2) @@ -238,7 +238,7 @@ You only pay for the message types you use. Strip whole message types with the m -DWOLFCOSE_NO_MAC0 -DWOLFCOSE_NO_MAC /* drop all MAC */ ``` -For common minimal builds, use a build profile instead of hand-listing macros — these are the supported, CI-tested configurations (see [[Macros]] → Build Profiles): +For common minimal builds, use a build profile instead of hand-listing macros — these are the supported, CI-tested configurations (see [Macros](Macros.md) -> Build Profiles): | Profile | Result | |---------|--------| @@ -251,7 +251,7 @@ A minimal Sign1-verify-only build (`WOLFCOSE_LEAN_VERIFY`) is about **5.1 KB** o ## See also -- [[Algorithms]] — full algorithm list with COSE IDs and wolfCrypt guards -- [[API Reference]] — function signatures, structures, and error codes -- [[Macros]] — every `WOLFCOSE_*` and `WOLFCOSE_NO_*` compile-time toggle +- [Algorithms](Algorithms.md) — full algorithm list with COSE IDs and wolfCrypt guards +- [API Reference](API-Reference.md) — function signatures, structures, and error codes +- [Macros](Macros.md) — every `WOLFCOSE_*` and `WOLFCOSE_NO_*` compile-time toggle - [`examples/scenarios/`](https://github.com/wolfSSL/wolfCOSE/tree/main/examples/scenarios) — `multi_party_approval.c`, `iot_fleet_config.c`, `group_broadcast_mac.c` show real multi-actor flows diff --git a/docs/PSA-EAT.md b/docs/PSA-EAT.md index 6894d578..ec77e1bd 100644 --- a/docs/PSA-EAT.md +++ b/docs/PSA-EAT.md @@ -87,7 +87,7 @@ Current ES256 Sign1 issuer without the PSA/EAT verifier: Replace the last gate with `WOLFCOSE_ENABLE_EAT_PSA_MAC0_ISSUE` for an HMAC256 Mac0 issuer. The same decode opt-outs apply. The algorithm gates can -then replace ES256 or HMAC256 independently as described in [[Macros]]. +then replace ES256 or HMAC256 independently as described in [Macros](Macros.md). These selective examples are useful COSE building blocks, but they are not RFC 9783 `#tfm` receivers: Section 5.2 requires a `#tfm` receiver to accept diff --git a/docs/Project-Structure.md b/docs/Project-Structure.md index 467c6279..9c3c7681 100644 --- a/docs/Project-Structure.md +++ b/docs/Project-Structure.md @@ -174,7 +174,7 @@ Test harness that: ### tests/force_failure.c / force_failure.h -Failure injection system for coverage testing. See [[Testing]] for details. +Failure injection system for coverage testing. See [Testing](Testing.md) for details. --- @@ -269,6 +269,6 @@ Do NOT include in production firmware: ## See Also -- [[Getting Started]]: Build instructions -- [[API Reference]]: Function documentation -- [[Testing]]: Test organization +- [Getting Started](Getting-Started.md): Build instructions +- [API Reference](API-Reference.md): Function documentation +- [Testing](Testing.md): Test organization diff --git a/docs/README.md b/docs/README.md deleted file mode 100644 index dc20216a..00000000 --- a/docs/README.md +++ /dev/null @@ -1,16 +0,0 @@ -# wolfCOSE documentation - -These Markdown files are the **source of truth** for the -[wolfCOSE wiki](https://github.com/wolfSSL/wolfCOSE/wiki). - -GitHub wikis cannot take pull requests, so the wiki is a generated, read-only -mirror. Edit the docs here through normal pull requests; on merge to `main`, -`.github/workflows/wiki-sync.yml` publishes them to the wiki. - -## Conventions - -- One file per wiki page. The filename maps to the page title: - `Getting-Started.md` -> "Getting Started", `Home.md` -> wiki landing page, - `_Sidebar.md` -> the wiki sidebar. -- Do not edit pages in the wiki web UI; changes there are overwritten on the - next sync. Edit the file here instead. diff --git a/docs/Release-Notes.md b/docs/Release-Notes.md index 396931d2..237fc8b3 100644 --- a/docs/Release-Notes.md +++ b/docs/Release-Notes.md @@ -125,7 +125,7 @@ initializes keys with `wc_CoseKey_Init()` and attaches keys through the messages using `ES256`, `ES384`, `ES512`, or `EdDSA` require `WOLFCOSE_ENABLE_DEPRECATED_ALGS`; changing a protected algorithm ID also requires re-signing the message. See - [[Algorithms#Migrating from RFC 9053 Signature IDs]]. + [Migrating from RFC 9053 Signature IDs](Algorithms.md#migrating-from-rfc-9053-signature-ids). - COSE-HPKE is experimental. Its wire format and API may change until the IETF specification is finalized. - `LIBWOLFCOSE_VERSION_STRING` is now `"2.0.0"` and @@ -151,12 +151,12 @@ MAC, and key distribution, and standardized post-quantum ML-DSA signatures or trailing input on decode. - All six COSE message types (RFC 9052): `COSE_Sign1`, `COSE_Sign`, `COSE_Encrypt0`, `COSE_Encrypt`, `COSE_Mac0`, and `COSE_Mac`, including the - multi-signer and multi-recipient variants. See [[Message Types]]. + multi-signer and multi-recipient variants. See [Message Types](Message-Types.md). - 40 algorithms across signing, encryption, MAC, and key distribution (RFC 9053): ES256/384/512, EdDSA (Ed25519/Ed448), PS256/384/512, ML-DSA-44/65/87, AES-GCM (128/192/256), ChaCha20-Poly1305, AES-CCM variants, HMAC-SHA256/384/512, AES-MAC, Direct, AES Key Wrap, and ECDH-ES+HKDF. See - [[Algorithms]]. + [Algorithms](Algorithms.md). - Standardized post-quantum signatures: ML-DSA (FIPS 204) at all three security levels, conformant to RFC 9964 ("ML-DSA for JOSE and COSE"). COSE keys use the RFC 9964 AKP key type (`kty` 7) with a required `alg`, the public key in `pub` @@ -173,7 +173,7 @@ MAC, and key distribution, and standardized post-quantum ML-DSA signatures against sign-disabled wolfCrypt (`NO_ECC_SIGN`, `NO_ASN`, no `mp_int`); the ECC signing helpers are gated out so a verify-only image never pulls in sign code, enforced in CI without `-ffunction-sections` garbage collection. See - [[Macros]]. + [Macros](Macros.md). - `LIBWOLFCOSE_VERSION_STRING` / `LIBWOLFCOSE_VERSION_HEX` in `wolfcose/version.h` for compile-time version checks. @@ -190,8 +190,8 @@ MAC, and key distribution, and standardized post-quantum ML-DSA signatures ### Improvements/Optimizations - Minimal footprint: an ES256 `COSE_Sign1` build is ~5.1 KB verify-only and - ~6.8 KB sign + verify for the wolfCOSE COSE + CBOR engine. See [[Footprint]]. -- MISRA C:2012 and C:2023 checked. See [[MISRA Compliance]]. + ~6.8 KB sign + verify for the wolfCOSE COSE + CBOR engine. See [Footprint](Footprint.md). +- MISRA C:2012 and C:2023 checked. See [MISRA Compliance](MISRA-Compliance.md). - API hardening: `COSE_Encrypt` and `wc_CoseMac_Create` direct mode now require an explicit `WOLFCOSE_ALG_DIRECT` and reject a zero-initialized algorithm id; `wc_CoseMac_Verify` classifies the recipient algorithm and enforces the algId @@ -208,7 +208,7 @@ MAC, and key distribution, and standardized post-quantum ML-DSA signatures `-fanalyzer`, Coverity), security scanning (CodeQL, Semgrep) and house-style gates, sanitizers (ASan/UBSan), a wolfCOSE <-> t_cose wire-interop conformance suite, and a wolfSSL version matrix with explicit ML-DSA/PQC rows. See - [[Testing]]. + [Testing](Testing.md). - Expanded negative and boundary coverage: 4 KB large-payload round-trips for `COSE_Encrypt0`/`COSE_Mac0`, empty-payload round-trips across AES-GCM/AES-CCM/ChaCha20-Poly1305, CBOR integer argument-width boundaries @@ -224,4 +224,4 @@ Assurance](https://www.wolfssl.com/about/wolfssl-software-development-process-qu page) and successfully passed the quality criteria. Requires wolfSSL 5.8.0 or later as the crypto backend; ML-DSA support requires -wolfSSL 5.9.2 or later. See [[Getting Started]] for build instructions. +wolfSSL 5.9.2 or later. See [Getting Started](Getting-Started.md) for build instructions. diff --git a/docs/Testing.md b/docs/Testing.md index 07030c61..096bab47 100644 --- a/docs/Testing.md +++ b/docs/Testing.md @@ -103,7 +103,7 @@ gate combinations. It also checks the 384, 521, and above-P-521 structural floors. `psa-eat-lean-verify` runs the RFC Sign1 and Mac0 vectors against a verify-only, full-`#tfm` receiver build. `psa-eat-demo` runs a complete issue, challenge verification, and software-component appraisal workflow. -See [[PSA-EAT]]. +See [PSA-EAT](PSA-EAT.md). ### Deprecated Algorithm ID Tests @@ -172,7 +172,7 @@ also covers missing, duplicate, wrong-type, wrong-length, and wrongly placed `ek`, prohibited `psk_id`, detached ciphertext, and cleared outputs on failed decrypts and encrypts. GitHub Actions runs the same coverage in -[Experimental COSE-HPKE](../.github/workflows/cose-hpke.yml). +[Experimental COSE-HPKE](https://github.com/wolfSSL/wolfCOSE/blob/main/.github/workflows/cose-hpke.yml). ### Comprehensive Algorithm Tests @@ -221,7 +221,7 @@ interoperability. t_cose verifies wolfCOSE's envelope bytes; wolfCOSE verifies the t_cose envelope and validates the RFC 9783 claims. t_cose and QCBOR are BSD-3-Clause and are not vendored; the -[Interop CI job](../.github/workflows/interop.yml) fetches them at pinned +[Interop CI job](https://github.com/wolfSSL/wolfCOSE/blob/main/.github/workflows/interop.yml) fetches them at pinned SHAs. See `tests/interop/t_cose/README.md` for the fixed test-key provenance. ### Complete upstream t_cose suite @@ -397,7 +397,7 @@ wolfCOSE is zero-heap (no `malloc`/`XMALLOC` on any path) and bounded-stack, bot - **Bounded stack**: built with `-fstack-usage`, then `scripts/check_stack_usage.sh` fails the build if any wolfCOSE frame exceeds 6144 bytes or is `dynamic` (unbounded); `-Werror=vla` bans VLAs/`alloca`. - **Zero heap**: sources, tests, tools, and examples are grepped for allocator calls. -- **`WOLFCOSE_MIN_BUFFERS`**: constrained-target profile that shrinks the caller working buffers (not the library frames) — see [[Macros]]. +- **`WOLFCOSE_MIN_BUFFERS`**: constrained-target profile that shrinks the caller working buffers (not the library frames) — see [Macros](Macros.md). - **Minimal Build matrix**: builds and tests against single-purpose minimal wolfCrypt configs (ECC-only, EdDSA-only, AEAD-only, MAC-only, …) plus a `WOLFCOSE_LEAN` core build. ### Lean and Post-Quantum Builds @@ -425,8 +425,6 @@ on-device build profiles: Nightly defect analysis via [Coverity Scan](https://scan.coverity.com/projects/wolfcose). -[![Coverity Scan Build Status](https://scan.coverity.com/projects/32918/badge.svg)](https://scan.coverity.com/projects/wolfcose) - --- ## Test File Structure @@ -472,6 +470,6 @@ Vector format is typically CBOR diagnostic notation or hex dumps with expected o ## See Also -- [[Getting Started]]: Build instructions -- [[Macros]]: Test configuration macros -- [[Project Structure]]: Source file layout +- [Getting Started](Getting-Started.md): Build instructions +- [Macros](Macros.md): Test configuration macros +- [Project Structure](Project-Structure.md): Source file layout diff --git a/docs/_Sidebar.md b/docs/_Sidebar.md deleted file mode 100644 index 6dc8afdd..00000000 --- a/docs/_Sidebar.md +++ /dev/null @@ -1,16 +0,0 @@ -### Documentation - -- [[Home]] -- [[Getting Started]] -- [[Message Types]] -- [[Algorithms]] -- [[API Reference]] -- [[Macros]] -- [[Experimental]] -- [[PSA-EAT]] -- [[Footprint]] -- [[Testing]] -- [[MISRA Compliance]] -- [[Project Structure]] -- [[STM32Cube]] -- [[Release Notes]] diff --git a/docs/assets/logo.png b/docs/assets/logo.png new file mode 100644 index 0000000000000000000000000000000000000000..4f4db6034157dd7c59d9953a06a18c7f5b213b30 GIT binary patch literal 12440 zcmeIZRalhY7e5L}BPHD+N`oNXFqCu-NF&|dNT*UNAOlF}3@}K;Pyzx<_t1zVUD7T8 zm+$XfoZIu9%X2Q~ooDZN?U=P!e)gJoI$A1(__X+FXlR70uN3vr(9p|(PX#XaLr;jj z5AcQVqo)EwgOAd00}V_Ec};mVwAxgH+c#K18_)BVF+fE0{o#Y2!A(SmhQ`mUswi&| zXtBQ>ngpKd=s!yCqpB)meT^=krIusp()}J!b0J0~CdQEN$MX#lr^#7aW~Xf5>?JyN z8!T5n7x%Qu5~ru(uQjum`o~|v8`xqDJ}s6!`%U1sF2d`pLsIoVT4%y!T5`}ZzT0s6i&KRVVIsT23Qd#3WS*wMTrlEKam z>-mgK_OAAIn+?WscT6&??H`NxQdA)Pf=7oPS?&JE(kIP*BpTl^qwu!mp8B;{zLFD)g zGsr=UDGW72NfM<0%~o9~P#m9f+i~hHL5E4kA87?bxrJOc9_?&3`tETU{;!MGX>Y5r z_XT@b;NAKbtk@lw%?iWxNulnvdBAEURod8L2;aQ-mLo3+@0+cGh9f4{rZUj*GT3lj^)hn;_$^)R;khx#8mZXMgM@3C;P z6gN;(yOyHRrPNyuJZr0Ra1mZmxK9Ie>^yG{znU8{noo)&q zw(DMAk^Oh3856HRr5Xq9G~INcF%d}&X;FMgu{0uy6+8QEg~3Lm!I3+5RPr(QBr2H| zns|gntr_>fYyRI!L&??d|Lx@yXk#H6{a3s8*$!2dDqc=HHG^G=)cMhYEpQ~)s1m_G zDaX|aU))w)U;6z|uE=FTsy3>`E5Vh`T&gpsJOeckdr2`=@dRGze+zF5e3z-C7r-!3 z^XRC^8lxR@GFUVGkWS|X7SSoz`B#zkHFopk!>40fR4H8+tAdXs z5le{N{2w%!}tQEJ?-FyJ+Q7T)S`7(e>b)H1wSybJiBF#cpp=&Sd9Ge`GZ(iW5 zGVpELWJ{olVv^wxwW$YA=uFyNOYIwyE7Ern86;YPSWKu&a(m1v@SgiEJN4(*2&)G3 z)qe3Oh_C{o? zP!r8DshacY*<2xF-$0z}?Riq}p!E6wY|(3d;SUa^ZY#=26^`Y$Er~<$rxl#oiBTi% zKRcs)asLVC*Ut_epAh4|-|}~>ngJ20Eje8EPeU%#{%5oP)5AQ$7Fk#?vFm=at z3K3{iL?^mde;|-fndMyn=tr|7_P)K2PZInJ{~6j03uGJ_E`8(RW2c=)WQLfWcKaNl zf)iW7W<*Y-J=sEP?k^{W%XV5a*lq9S$i6SV`Q!=AKnTk0!Qu2tVdbb~ul7VnCW0Tr zmja)5Y&(c8FSr~DZ2SX4i3cG@-^YD|m3$~))+*ipC0MS_6uu%jy26y5^)IW{^Y$=Q z%ME8I$qHmd>*2*`T>0j@?Y)#W04_kbuUO8fZWDNC@l zj6eHf$%pAv-&nmBJ|(nGRtWz)`yWn(sRUqt7`f{@jnQCP%;q-b&=l`{>a0WP6{^>F z0zHzSn>fvt#?R#&#VbDGM02Im7{Y>kReZ1_LE|bMoYXVsSMg(ET+7B$Iv72L);;1u zu+r7g>$F)LuAsKR$9p930mNa=iw*p4=;<6QK}~5J5eFUx*{E0b=jqb*m*ZXQKxFv zpG~AjeZNfl-l7yvazUzNvWMbY!MqE;O#o}S3<63K3XLP5;N}iY7(h7CxD+mFNXy!L zGCX4ipBk&@4RhrrIX(z2*O>&(KP7L6O;3ZN0zy5wf1|CO#WOj7XG85xM=B=#a}$0^ z2%8n^C~Q3R};qeby)H=76T9Jh>e z@oERpM;OBPd=9>^tF(rAjVw*nnR%V(Rr(Y-#pxb%#9qW-+_KMlfh`8~COR(MW7g)G zc*H@7zd~UdqUi>?)nWg%M+b%<{fM`6=0v)GZS>iv3jg=}EOTVW3ikQH#EL06cm6wA2i7WX2}ll49EG>Q+*4c|Z^@c(KQk-ViwJr`EzaG@$$y zZK?KKQ|$Cs*l~Eizy-EG6{O$6wL%~O>ImYS&5&Ar?Bq6mK~Kf7IEhIddwZ+Sr}hxG z93f?-@2+D}mYYfJzj&gcvC|Aq2dOy29o??I3S^jOqdwkQNd<@1UW}Q}8X0;1cmahv zgKZ)(I&{ps-C<(lo~VnTd6i_{ z_yL;2&$h;ojy$S@|F)VQ-LgVV6bWn9BjyY-_?Dybi5FGTvu6*E-(D(qU^4jkA+0OHxU-?l==doCe+HmH_${U(hUSN!7du69b#w+H#u`EE}NRiMoQ%YCvm|3V&mQdV(XYC0W{r{XsyTU0e6G3U@~BYT>&q;n|@`4-L*@ zv>hWFXkw}-1~#xE5MdoJSfpv$S_@^U;J+LVUk>C`@owRpoe6o<#<%mUJ9+~q+Ji@( zWaa#h)uYP>j(sz&WCW?~eux!YX@~unoX7BPxHJHfz1t>aY9!hoU;#9w;e1nL;GjAG=2n9@_|F%AjkDGB*{IX%duL((ewtI8 zxf~ZCKlKd*uowM516GBNqPM>=)A7~cn!&zG+YojC`TDbJNJ9#1yMw9L5_c~eaf!ba%weN6JN5LrQbF=;^*Vf_FDc#>9X8k>`4p;AnfL$i~ zNty?(XZ!??Xt={#2)lHdHA3Vm#6)h{ris%0ul$34Ji}UiM|^XC^!b4~)=@5^E1A6I z@d0`X6_ZD;y}ih;e}4A6g&BYpd2Tc2h=(Ftj|co~;VlMlnpQ=p+3IQh+MK2glL@aL zv+>TExB0tWvyZc3lCjn1mi(H$MffJp$5jlS`ea)9&)bUB+YAu-tmj8*>HiGHW+ah} zf?{dqiQB+$uQG>Hh(DXV^UZux&nzA)GFdbZ%XRO%^Y@`pZbCAWJsqb6w7NxOH&3<~ zj*my`|G-}@s2`2xV10pMIIu4Y5`e&rYxc@y^F3 z3?VAAm^>}pgfh6wfZvw!L<3fZIZI3i(XDomm2 z%QTN;Kc(bab_6$G;qymgHOb*klL(H!l$Y>y;WPjHyNev|1{&ZM`pB>;pfS5tOaAo%hZa$7>$q$MAPpwjd_YuV z&WpH-D@djW#>%o`Wl`S zkE&!^giK`MD9UXLL)E@rK}wM_z+N$Zl}Qn%wbodL%P$|A(|?_J#0WhDU=aWPg+7a5 zUim&uMLEKQN5oQA2XDBNMRmm+aVW@0NHrN8L=#pjzAOOJ^|Z*G*}Zk0k}FyUw|t|R zn>ZnXGCd_ZS%9FL7@Usp!8Nq;6cT~!H60iZ;}PEYE>Uj((1u!DuepWq9GG>5g$5Vz z)*DmXU_34DH#9fglaYZSS`}#2xG^^@+Ld;B)3j2=_^6J6^1jY&|srU z3jYfh0p+tqsux-tBRNRn7{tU0kN4%9b7~gQ>+TZ$=z8SKtuqehR3_Oxnat6}tu4pv zj%mNk?_}Ei9jk&-con3=@8N6dBd^l{=OT4iKgAHR^aeg!hnF9AN}q_GRyOED8<3cQcfSDk!kHOo z`smc|c;Yqpk_6JTPmEyn>=DKuz#Gk0-z>XFXLg*ExyY+~=bctI+KOF0l$HzvFH~2@ zyTyiDBMi;ib)mrt2p9;*Gv~h&6B4dxw-<1!MouSpTJr3+4u;7t#=OU?5Xg+H-D7>) zP$8W9T>Ueo@&u};%WNRMCPzVENKVv^ISrxww!qaks56u1a9e80Z%6(Zks*ChG7z#? zI{) z{c%LLPgWMYjg3ud>d4%I*oud89mAx9-`_uPvb>k1D-0mO!H@?O=Xui{P=jpD9 z!k8U5YXJ}73P_^uJ2N_DE!cAy7#hkMn1L><+yQHj7Ff2~wuqp8#<12uA5Q;R09A+3<2pBmK?))24U@76B6re)Pr`W^>@>Kw)+7V6o zU#iq`LTiBGCPa^tQeV`AkQ6&$HMF^P2aZ%EWPZ?>QhpO4)(wuT2C+-l3a4RBU7zhv znKlnTSL8p-M&xZbRb<9CZYctkB_t-b)=Fb2ZgMficGs?OXWE@;=l((?H(?(%L$^!q zUElxcPXG22Uo30A8Ymw+LJdsGmg~K;y-)U-zhI=JQ$Igg&RJOrzrX7o6IGNe>I6DU$0A5>XiwaWOZ@m;HjUNePEh>npzY^B{qm93)26+_p($C9{|i^%JV5GRFRX^K zhc2^^eNjEXM^&GWg>6`RA6@Pjod!Q3hbEQ^)W89I{s*Kxj?F=jlmk6+=MhJB>Qjq# zg+pl>_3{0Wb{}nc{4Qc%xY~JlDjm3yEBXnk)#>oBObp96n2xwoBHqsxm(74pQibCg zLpt*C)uGODyGXu@Tm|Wh|6Zf*#Wu1-3*PA)GT?p@(Mx=L>ki-7ocheV@dxWQ>^7%V0+yLgc$8&AZb=6|r1 zMGvU+gKxNQEMlqLtk^V3r~MsIbl=g?-$Exm{*Yw;fnOohSC&iVg17z-{d{2&-r68{ zpq%mN0oH!Fmgv-5>S51+X|%T0+xNob3esxC5QUck)#u-iXaj-?-^q8iG8BYt(#7|* z_lnhOoNUftR46S>)v!wC{>^i%a1oY3$tNH3PbUgvgPf>$#zEiEazxzJ9ufze?xC$P z-$uLB(m$*Hbk%bpRdUMw)eAF;QHuBdA3Fa|pZpBPu}I=dR~&O#W+E;T1^avj1Yf#B z%>?1=R0l**rxGI0ThqVX#C@mVKG!lv-7?*aI(Pm~?Fl?P35PZ8PR2zUqcfo5MT8okECO}Z-duXM2AXuaUD{DQfO3rZ!eEo~|7ajL?PZvLHKtq7a% zoU4#d+JUKl=rj#aH!?$hEXQ*v)e55wSGc>ID!Fu8ApK?VK`>zu^tTDq(bzygv1Kp| zp^+~zf&LPpDH~iew8i5wQHUv*ACfCY?~D1C13I>@TqvI-08>K*OK;HPG+dRsr1AlW zXKQY$y)i8JY79Fy*_zxBEViz8UANuF=O?^=d^Kunp?=7F^tjd24*s#%h(vXR; zVBkjKYb%m2WF7svqdLFz<*(>ag#qO>WM>5ny{~NySHJeZL%|J;`nfoCfaWi#@U>8S zNs^j8T}leimrM~2#I}CB|4*Wkje?#!uIC*q0GcXs!MJsYn+$J10ggtlc{Qx9m8&c% z?yCEUgn_108=$+{G;o1H6eX3Wn-k02D%51J^cZNI(_-}5b5rK=I zuTbigTfw)z%PwD3R03j%92m}0@E#378l)2sIU53&yyE@3x@a}?U71W1d6>d3-}sC% zS=Ok?7v(1tRh_gl`>yrG{v6EUP6JmOKCd*Y5wRpxV4*RYvC*Itb?3PiH0s^A32zMx zyV%w~mzsWYimH66Yd4$9C~KRU347+ZcJ}1@=C_) z*Aapj^EHHlaH0{rfa@&kxC6OkmA(fr$K8==FieY8emqx=?#_k^CD7sulgmIq)`@cp zecx>g-E%)RJLtSQ7(^_d3Z5|NfN|1Rrl1|@58ekkj*@DsAJv9 zaWrWxB~~b7md>no`kq`n$nk56@Iy|Wv~fzWY!~I?D@fK${)0WnwI+_jqgx+sfJ7-SyxQojBbG0@bgG@Pa{yS0dn2vr% ziRsK(G2PuQxmIVJ#KiK?fV(f33+h{k#4WVc8Vky$T!k_j#Iy>yy1eh~F&A(JI@fbB z>WRkc@jx|eoHofM*NgY5&BGM7R{U4g>RV-l@B-98YEI<=?5(@=*6#EinUG#eZn-$FdHE6;(O*hw=MY{PEy9#krjMIs2q zn_h0!Ryx|A1ta0+E(bH}v(;3nKx*tMAy>Cg3-){MB$RFZ3?#ek^B6Y{VxpD`OeUgIv~~a86yUh+)?Jly`Ib2zL>lI za~RT$x81xL%SJry>;uUBSg;VsL0KkIfVdn5+mXyZ02^?<&TX|62OoXH41w zerr-^`woZ_$DaRjnIT%k$B!*?cfKY6#Nw1@d^zQU^jMwFZ4A2&5J;(jE1$Cz?5D}Y z4Ckw)-g!wq{q9ayXVs12Bb=2|jk}!}av)$t)_^pBRcM*^V#nJ+CtwBi7I!xttgP>G zhmhU0^#0h2uf0~1`(5FnBv*xoOztH`p=2y@o+3 zFYq@WfYvnU=TK_KyGEQvvi1`*=x<9yg1Hr%2WG0Nz#4_bupG4ksS2-@b=#RM!9ggk zpoGBd85>vhWy%ag4Hk!$bqeR~U|=%;!xcC9?JjaI)-V$W<@*n;0y8FWR{`+0uFz<& zk9|(%aYgVjM)nTWY_|IkLa-^>0wrEp`F#6~nuYS+IX*6!0?eyM$Y8?aALk*+ps5>M z<@K*ef6PcC*QBf3&M29t!`;tgC)8>WN)N1E*ze=&>moLU`(2BL@^}HiR-`)3{=PfE zFI3BjHyY7oAZ{QoV0Be$lvU|m;eC7Cxj8Ao5o5=o(Ijcpwnc#%-Sqgla9C##oSS|m zG4U8|_&9f(qtXjr6ymWy^F}1yzYt$YH==Ke9p=#>sbPvpS6*{+Uzs)83Fc*ylXH&G>HaW%^E-G6}*e%j*V zceWvfzo~TBLBpdYk0}y-Q7oAI5ezOf%+6oH;<2;=6BTY%=D{=!ofQ#ftKV|<`D3ZS z=Lb7lW>M(V6wWmqXn&VC50=Pd-tc^q+!h0)x0We-S{z}BWK8s47Q@m{(7xBd7~-yv z+A*`G<04V;4ad;S^we7?abAM*t(7RXCP~iw;Fpo0p6fTS)A;VSYUjQo{~uiz&zEVr z0gW^ake|zTZlsGhVa0eNqg;w==<7W3 zYcq5WrBis4+A^a&X@{>w#T2o|X_W04`HlLU#0@k!^bN(oFEy5X;)`bl+g>gR6<8BF z#**1+b%@{p0lB`)_FDye?Kqu7Sh&jA+}2{Qe<04AR@ylh`i*V0SSqpowmA!IEDlQr z*sq-sKL4r-1t9qh)UW%l6j_)Azf)>O@CpwKq_#OWS^Q9H!FP=H8Ah*m*ZeYeRZdal z!j%)K)At=mnoaUeF|^K$N;4^;*6ZI!cNe76vo0c~HdwEj&E?DJ=4}qGH!IRYr8>T3 z;IW^-P6BExQc6g``bIN90Upd%`6i_`_!_9zfN2?wzZXu_nN85|K;nP&8MXAS$W zgD4b|X3~0$m$M-scAKXH0xS##zyfxr1i=b^EOBBfj2v7|JE|xRySx}Wo3n-!a2%OL zA9%`8uFyb<>ZwlY9ITv+b^`({UoN*4HTuB8#irY6pwvh1ZOG^XA!&OJEB{b`a{Uul z4tr#>90cyb5g0s6!>#=cnP$##$HCjKczvkzVp~8>t7ulvmWk3oXfeIxt()B z6#6_U4&!EPo~gc^hD_!U{{?BV++g0fvEi{%oc&o20x|kLHs)wLDnRpdqeQN`vViaA zL@bsNnSTF}?v}YldthxVY;^kIJ2j|Vgx+QWit)`Vk?*pg74!-i6315wU4AE!bU25t zr6CEvRGz`jAB2!51d`*IQPbu_#|n48mf(YM-JBpVl5YLHg_OkcvGgD3UzQub0>_sQ zh4h34f3pSO?KYav(FHG-G->}Fdl(9fhDz!fFns3grtYOS=MXq3eeEFeg5z0kfY6VB z;q7*C7-^kzgYlfp2_psgEd4DwMq-2Ya0Gc}9vh_!BPxf=8=RfIA)GSS$hvUZVF~M; zrw3jBr!@Ao2Eu*q+_5iUxPIs0m7JPh9s(Tw849uOwX0(5}F6gBE_aLqK(Lag9 zVpsg+lGS9dZ^oBjM{^a8qg+F@z6cpDyGi;lnZ=SJUcwW5x()0eP4CuLK331XU_CwA z3wYx4L*FFUM)r0R{)h!RUXt&B;|pHCKvIo>{Xn7%cTp;bW24Ca;SNubQNN$=rD(?> zywV~KXXn_-Ji~m;EtiNv!WPaZ8ThxL^;r8*b|CDMDwuEtAO<<$}c^FnaYZ;h=)SufBwR>qD72mHdnkiITAV z%;Y;V_F?J!o#XBTcTj*G=UbVR8`)=;fjd_|(ensPHD}R@>Y+wiUnJ2Sbh~GMy9EIHR;? z1@q=9G~zI9l;Ic)sr6o0^Px!TaoV0N{rUH=XIU-O_VJR?#}0V4ROIe*BQ^aZ3ccXgq>1PyBR7y$_jY;ij3AbRA;WqEvGeJXF9N&P)f4e)j8cf>_#PSQyA_{ z%jtCcmCxB!fG~KNt3T^~JF(v(M#!&79BNappB+rCa9zTa@Ref$A3K$`+yA1WvvMo@ zw@xo#bS;B5#u!f_ev9#1g@D18@TsvlZQs3K+I_Wb{D9hQSac)<8N3V15KOJvZ7E+nrar~8eRR_a)bvsQe4~qz8{+#Z}JTxk363RdZhqHfsWQD*bo zs;0FPq&AgBKqG?+Gabar`~Zy=lu+^v$a!tg72KKODA z?yV_jMAL3QR54BXl5swprmobTJt5HS%AH5`>B#ShZ}mojvfz>-D`DPtjHPapDEKfZ zs*w0@%GVVuy+i1DSK4-P{fGkfs>7eGz{X4G>TH)g5o`C-wDCm8Ad6c*Lg0Se{S;owhO;{{oAyCL{bK0r=kX$_XU= zr;-JN3$F}&@?fnA2VD=ZF_qRy*jr-78Yp`D8F{hdi_abVfrxkdO4T{ZFT!#;EOF9? zw_huzi|X)8h^*O`UnP1cklJtGeBB$&GEib9)j%7ah`hPqnRqoI2K^?QYq7Z7U|~6f z29!YnCFIccDk(HMAAl;Ng5>{y{J-Ww!n2?Ek9HlC@kGi}(t&>yps6ZpDZ)WkQU3>E CMaP@~ literal 0 HcmV?d00001 diff --git a/docs/assets/skin.css b/docs/assets/skin.css new file mode 100644 index 00000000..3ad8a7ef --- /dev/null +++ b/docs/assets/skin.css @@ -0,0 +1,25 @@ +/* Match the public wolfSSL manual colors without depending on its build repo. */ +.md-header { + background-color: #fff; + color: #1fbeca; +} + +.md-header__title, +.md-nav__link--active { + color: #1fbeca; +} + +.md-typeset a, +.md-nav__link { + color: #c46715; +} + +.md-typeset a:hover, +.md-nav__link:hover { + color: #1fbeca; +} + +.md-header__button.md-logo img { + height: 2.5rem; + width: auto; +} diff --git a/docs/dev/DOCS-BUILD.md b/docs/dev/DOCS-BUILD.md new file mode 100644 index 00000000..7d6041f7 --- /dev/null +++ b/docs/dev/DOCS-BUILD.md @@ -0,0 +1,68 @@ +# Building and publishing the wolfCOSE manual + +The top-level `docs/*.md` files are the manual source, one per page in +`mkdocs.yml`. The adapter in `tools/docs_manual.py` passes those pages to the +shared MkDocs theme and Pandoc/LaTeX PDF rules in +[`wolfSSL/documentation`](https://github.com/wolfSSL/documentation). Keep manual +content and its navigation in wolfCOSE; generated files stay under `build/`. + +Anything that is not a manual page goes under `docs/dev/`: maintainer notes +(like this file), drafts, scripts, or diagrams not referenced by a page. +`mkdocs.yml` (`exclude_docs`) and the adapter (`tools/docs_manual.py`) keep that +directory out of the published HTML and PDF. Never place a non-manual file +directly in `docs/`: the build requires every top-level `docs/*.md` to be a page +in `mkdocs.yml`, so a stray file there fails the build. + +## Local build + +Clone the documentation build tools at the revision used by wolfCOSE CI: + +```sh +git clone --recurse-submodules https://github.com/wolfSSL/documentation.git build/documentation +git -C build/documentation checkout "$(cat tools/docs-manual/documentation-rev)" +docker build --pull -t wolfcose-docs:local docker/docs +docker run --rm --user "$(id -u):$(id -g)" --env HOME=/tmp \ + --mount "type=bind,source=$PWD,target=/work/wolfCOSE" \ + --workdir /work/wolfCOSE wolfcose-docs:local \ + python3 tools/docs_manual.py build \ + --documentation-root /work/wolfCOSE/build/documentation \ + --source-root /work/wolfCOSE --target all +``` + +The outputs are `build/documentation/wolfCOSE/html/` and +`build/documentation/wolfCOSE/wolfCOSE-Manual.pdf`. The container includes +MkDocs, Pandoc, LaTeX, and the fonts used by the shared build rules. On a +wolfCOSE pull request, `docs-site.yml` checks out the pinned documentation +revision, builds both outputs, runs MkDocs in strict mode, and uploads them as +one artifact. It also runs after documentation changes merge to `main`. +CI pulls the versioned builder image from GHCR, or builds it from +`docker/docs/` if that image is unavailable. No host package installation or +website credentials are needed for this check. + +For an HTML preview, first run the build above, then run: + +```sh +docker run --rm --user "$(id -u):$(id -g)" --env HOME=/tmp -p 8000:8000 \ + --mount "type=bind,source=$PWD,target=/work/wolfCOSE" \ + --workdir /work/wolfCOSE/build/documentation/wolfCOSE \ + wolfcose-docs:local mkdocs serve -a 0.0.0.0:8000 -f mkdocs.yml +``` + +## Website update + +The one-time integration in `wolfSSL/documentation` adds a `wolfCOSE` manual +target beside wolfBoot and wolfHSM. It clones `wolfSSL/wolfCOSE` **main**, runs +the adapter from that checkout, and exports `wolfCOSE-html/` and +`wolfCOSE-Manual.pdf` through the documentation repository's existing Docker +build. Merge the wolfCOSE adapter before that integration so its source is +available on `main`. + +After both changes are merged, the existing nightly documentation build should +pick up `wolfcose` through the documentation repository's `all` target. No +manual trigger is needed for the normal update. Check the first nightly result +at `https://www.wolfssl.com/documentation/manuals/wolfcose/` and its +`wolfCOSE-Manual.pdf`. The website upload rules are outside these public +repositories; if the nightly publishes an explicit list of manuals instead of +all build output, that list will need a one-time addition. Subsequent merged +wolfCOSE documentation changes are read from wolfCOSE `main` on the next +nightly run. Pull requests only build review artifacts. diff --git a/docs/index.md b/docs/index.md new file mode 100644 index 00000000..bacd125e --- /dev/null +++ b/docs/index.md @@ -0,0 +1,84 @@ +# wolfCOSE + +wolfCOSE is a lightweight CBOR and COSE library for embedded systems. It implements: + +- **CBOR** (RFC 8949): Concise Binary Object Representation +- **COSE** (RFC 9052/9053): CBOR Object Signing and Encryption + +It uses [wolfSSL](https://www.wolfssl.com/) as the cryptographic backend and is designed for constrained IoT devices, FIPS-bounded deployments, and anywhere you need authenticated CBOR payloads in minimal RAM. + +## Standards + +**Core specifications** + +- [RFC 8949](https://www.rfc-editor.org/rfc/rfc8949): Concise Binary Object Representation (CBOR) +- [RFC 9052](https://www.rfc-editor.org/rfc/rfc9052): CBOR Object Signing and Encryption (COSE) structures +- [RFC 9053](https://www.rfc-editor.org/rfc/rfc9053): COSE initial algorithms +- [RFC 9864](https://www.rfc-editor.org/rfc/rfc9864): Fully-specified algorithms for JOSE and COSE +- [RFC 9338](https://www.rfc-editor.org/rfc/rfc9338): COSE countersignatures + +**Post-quantum cryptography** + +- [RFC 9964](https://www.rfc-editor.org/rfc/rfc9964): ML-DSA for COSE +- [RFC 8778](https://www.rfc-editor.org/rfc/rfc8778): HSS/LMS hash-based signatures for COSE + +**Attestation** + +- [RFC 9783](https://www.rfc-editor.org/rfc/rfc9783): PSA attestation token profile of EAT + +## Key Features + +| Feature | Description | +|---------|-------------| +| Complete RFC 9052 | All six COSE message types — Sign1, Sign, Encrypt0, Encrypt, Mac0, Mac | +| Multi-signer / multi-recipient | Full `COSE_Sign`, `COSE_Encrypt`, and `COSE_Mac` support | +| Post-quantum signing | ML-DSA (FIPS 204) at all three security levels — first COSE library to ship native PQC | +| PSA attestation | Optional RFC 9783 EAT / PSA token verifier and issuer, including Sign1, Mac0, legacy consumption, and PSA/HSM delegated signing | +| Zero dynamic allocation | Heap-allocation-free, non-recursive; caller-provided buffers within a bounded, target-customizable stack ceiling — zero `.data`/`.bss` | +| Tiny footprint | 3.5–5.1 KB COSE engine, 5.1–6.8 KB with the built-in CBOR engine (verify-only -> sign + verify); 26.2 KB -> 34.6 KB total with wolfCrypt — ES256 `COSE_Sign1`, dead-code-eliminated | +| 41 algorithms | Signing, encryption, MAC, and key distribution — classical and post-quantum | +| FIPS 140-3 path | Sole crypto dependency is wolfCrypt FIPS Certificate #4718 | +| CNSA 2.0 ready | ML-DSA-44/65/87 for quantum-resistant signatures | +| MISRA-C:2023 | compliance striving, Single-exit pattern, no recursion, deviation-logged | + +## Documentation + +| Page | Description | +|------|-------------| +| [Getting Started](Getting-Started.md) | Prerequisites, building, and quick start examples | +| [Message Types](Message-Types.md) | All six RFC 9052 messages (Sign1/Sign, Encrypt0/Encrypt, Mac0/Mac) with code samples | +| [Algorithms](Algorithms.md) | Complete list of supported algorithms with COSE IDs | +| [API Reference](API-Reference.md) | Full API documentation for all functions | +| [Macros](Macros.md) | Configuration macros and compile-time options | +| [Experimental](Experimental.md) | Draft feature status, supported scope, and graduation plan | +| [PSA and EAT](PSA-EAT.md) | RFC 9783 PSA attestation profiles, APIs, and integration guidance | +| [Footprint](Footprint.md) | Size and speed numbers, desktop and on-device | +| [Testing](Testing.md) | Unit tests, coverage, and failure injection | +| [MISRA Compliance](MISRA-Compliance.md) | MISRA C:2012 and C:2023 compliance status and deviation rationale | +| [Project Structure](Project-Structure.md) | Source code layout and file descriptions | +| [STM32Cube](STM32Cube.md) | Install and run wolfCOSE as an STM32Cube pack on device | +| [Release Notes](Release-Notes.md) | Per-version changelog and release highlights | + +## Supported Message Types + +wolfCOSE implements all six COSE message types from RFC 9052: + +| Message Type | Tag | Description | +|--------------|-----|-------------| +| COSE_Sign1 | 18 | Single signer digital signature | +| COSE_Sign | 98 | Multiple signers | +| COSE_Encrypt0 | 16 | Symmetric encryption (single key) | +| COSE_Encrypt | 96 | Multi-recipient encryption | +| COSE_Mac0 | 17 | Symmetric MAC (single key) | +| COSE_Mac | 97 | Multi-recipient MAC | + +## Quick Links + +- [GitHub Repository](https://github.com/wolfSSL/wolfCOSE) +- [wolfSSL Website](https://www.wolfssl.com/) + +See [Standards](#standards) above for the full list of implemented RFCs. + +## License + +wolfCOSE is free software licensed under GPLv3. For commercial licensing and support, contact [wolfSSL](https://www.wolfssl.com/contact/). diff --git a/mkdocs.yml b/mkdocs.yml new file mode 100644 index 00000000..e84f3b44 --- /dev/null +++ b/mkdocs.yml @@ -0,0 +1,63 @@ +site_name: wolfCOSE Manual +site_description: Lightweight CBOR and COSE library for embedded systems +site_url: https://www.wolfssl.com/documentation/manuals/wolfcose/ +repo_url: https://github.com/wolfSSL/wolfCOSE +edit_uri: edit/main/docs/ +docs_dir: docs +site_dir: build/docs-site +copyright: Copyright © 2026 wolfSSL Inc. +use_directory_urls: false + +# docs/dev/ holds maintainer notes (build process, etc.), not manual pages. +# Keep non-manual docs under docs/dev/ so they never enter the published manual. +exclude_docs: | + dev/ + +nav: + - Overview: + - wolfCOSE: index.md + - Get started: + - Getting Started: Getting-Started.md + - Message Types: Message-Types.md + - Algorithms: Algorithms.md + - Reference: + - API Reference: API-Reference.md + - Build Options: Macros.md + - Project Structure: Project-Structure.md + - Attestation: + - PSA and EAT: PSA-EAT.md + - Compliance and size: + - MISRA Compliance: MISRA-Compliance.md + - Footprint: Footprint.md + - Testing: Testing.md + - Platforms: + - STM32Cube: STM32Cube.md + - Status: + - Experimental: Experimental.md + - Release Notes: Release-Notes.md + +theme: + name: material + logo: assets/logo.png + favicon: assets/logo.png + features: + - navigation.sections + - navigation.top + - content.code.copy + palette: + primary: white + accent: deep orange + +extra_css: + - assets/skin.css + +markdown_extensions: + - tables + - admonition + - pymdownx.details + - pymdownx.superfences + - toc: + permalink: true + +plugins: + - search diff --git a/tools/check-docs-no-internal-links.sh b/tools/check-docs-no-internal-links.sh new file mode 100755 index 00000000..cdbeb0b1 --- /dev/null +++ b/tools/check-docs-no-internal-links.sh @@ -0,0 +1,49 @@ +#!/usr/bin/env bash +# Docs guard. docs/ is published as the manual, so the public tree must never +# point at an internal ledger or at a developer's home directory. +# +# tools/check-docs-no-internal-links.sh [path...] +# default paths: docs README.md +# tools/check-docs-no-internal-links.sh --selftest +set -u + +root="$(cd "$(dirname "$0")/.." && pwd)" +PATTERN='internal-docs|/Users/[A-Za-z]|/home/[A-Za-z]|~/[A-Za-z]' + +selftest() { + local dir fails=0 + dir="$(mktemp -d)" + printf 'See ~/wolfcose-internal-docs/task-list.md for the rows.\n' > "$dir/bad1.md" + printf 'Logs live in /home/aidangarske/wolfcose-work.\n' > "$dir/bad2.md" + printf 'Run `make test` first.\n' > "$dir/ok.md" + if grep -qE "$PATTERN" "$dir/ok.md"; then + echo "SELFTEST FAIL: clean doc flagged"; fails=$((fails + 1)); fi + if ! grep -qE "$PATTERN" "$dir/bad1.md"; then + echo "SELFTEST FAIL: internal ledger link missed"; fails=$((fails + 1)); fi + if ! grep -qE "$PATTERN" "$dir/bad2.md"; then + echo "SELFTEST FAIL: home directory path missed"; fails=$((fails + 1)); fi + rm -rf "$dir" + if [ "$fails" -ne 0 ]; then echo "SELFTEST: $fails failure(s)"; exit 1; fi + echo "SELFTEST: ok" + exit 0 +} + +[ "${1:-}" = "--selftest" ] && selftest + +cd "$root" || exit 2 +if [ $# -gt 0 ]; then paths=("$@"); else paths=(docs README.md); fi + +echo "docs guard: no internal-ledger or home-directory references in: ${paths[*]}" +hits="$(grep -rnE "$PATTERN" "${paths[@]}")" +rc=$? +if [ "$rc" -eq 1 ]; then + echo "OK: no internal references." + exit 0 +fi +if [ "$rc" -ne 0 ]; then + echo "FAIL: grep error $rc (missing path?)" + exit 2 +fi +printf '%s\n' "$hits" +echo "FAIL: $(printf '%s\n' "$hits" | wc -l | tr -d ' ') reference(s) to internal material in the public tree." +exit 1 diff --git a/tools/docs-manual/Makefile b/tools/docs-manual/Makefile new file mode 100644 index 00000000..18c2a39b --- /dev/null +++ b/tools/docs-manual/Makefile @@ -0,0 +1,15 @@ +.DEFAULT_GOAL := all +include ../common/common.am +include build/order.mk + +SRC := src +PDF := wolfCOSE-Manual.pdf + +.PHONY: all html-prep pdf-prep +all: pdf html + +html-prep: + @true + +pdf-prep: + python3 "$(WC_SOURCE)/tools/docs_manual.py" pdf-links --documentation-root .. diff --git a/tools/docs-manual/documentation-rev b/tools/docs-manual/documentation-rev new file mode 100644 index 00000000..66273b3c --- /dev/null +++ b/tools/docs-manual/documentation-rev @@ -0,0 +1 @@ +9455a759732a45c2ec1d408956105019ec9ced21 diff --git a/tools/docs_manual.py b/tools/docs_manual.py new file mode 100755 index 00000000..a64fd639 --- /dev/null +++ b/tools/docs_manual.py @@ -0,0 +1,181 @@ +#!/usr/bin/env python3 +"""Build the wolfCOSE manual with wolfSSL/documentation's shared tooling.""" + +import argparse +import json +import re +import shutil +import subprocess +from pathlib import Path + +import yaml +from markdown.extensions.toc import slugify + + +MANUAL = "wolfCOSE" +PDF = "wolfCOSE-Manual.pdf" +HEADING = re.compile(r"^(#{1,6})[ \t]+(.+?)[ \t]*#*[ \t]*$") +LINK = re.compile(r"\]\((?:([^)#]+\.md))?(?:#([^)]+))?\)") + + +def pages_from_nav(value): + if isinstance(value, str): + yield value + elif isinstance(value, list): + for item in value: + yield from pages_from_nav(item) + elif isinstance(value, dict): + for item in value.values(): + yield from pages_from_nav(item) + + +def page_key(filename): + return "wc-" + slugify(Path(filename).stem, "-") + + +def heading_slug(title): + title = re.sub(r"[`*]", "", title) + title = re.sub(r"\[([^]]+)\]\([^)]+\)", r"\1", title) + return slugify(title, "-") + + +def stage(documentation_root, source_root): + manual = documentation_root / MANUAL + source_docs = source_root / "docs" + shared = documentation_root / "common" / "common.am" + if not source_docs.is_dir() or not shared.is_file(): + raise RuntimeError("wolfCOSE docs or documentation/common.am is missing") + + config = yaml.safe_load((source_root / "mkdocs.yml").read_text()) + pages = list(pages_from_nav(config["nav"])) + if not pages or pages[0] != "index.md" or len(set(pages)) != len(pages): + raise RuntimeError("manual navigation must start at index.md and contain unique pages") + source_pages = {path.name for path in source_docs.glob("*.md")} + if set(pages) != source_pages: + raise RuntimeError( + f"manual navigation mismatch: missing={sorted(source_pages - set(pages))}, " + f"unknown={sorted(set(pages) - source_pages)}" + ) + + manual.mkdir(exist_ok=True) + for name in ("src", "build", "html"): + path = manual / name + if path.exists(): + shutil.rmtree(path) + shutil.copytree(source_docs, manual / "src", ignore=shutil.ignore_patterns("dev")) + shutil.copyfile(manual / "src" / "index.md", manual / "src" / "Home.md") + (manual / "build").mkdir() + ordered_sources = ["Home.md" if page == "index.md" else page for page in pages] + (manual / "build" / "order.mk").write_text( + "SOURCES := " + " ".join(ordered_sources) + "\nAPPENDIX :=\n" + ) + (manual / "build" / "order.json").write_text(json.dumps(pages) + "\n") + shutil.copyfile(source_root / "tools" / "docs-manual" / "Makefile", manual / "manual.generated.mk") + + config["docs_dir"] = "build/html" + config["site_dir"] = "html" + config["theme"] = { + "name": None, + "custom_dir": "../mkdocs-material/material", + "language": "en", + "palette": {"primary": "indigo", "accent": "indigo"}, + "font": {"text": "Roboto", "code": "Roboto Mono"}, + "icon": "logo.png", + "logo": "logo.png", + "favicon": "logo.png", + "feature": {"tabs": True}, + } + config["extra_css"] = ["skin.css"] + config["markdown_extensions"] = ["tables", "fenced_code", "toc"] + config["plugins"] = ["search"] + config["use_directory_urls"] = False + (manual / "mkdocs.yml").write_text(yaml.safe_dump(config, sort_keys=False)) + + header = (documentation_root / "wolfBoot" / "header.txt").read_text() + header = header.replace("wolfBoot Documentation", "wolfCOSE Manual") + header = re.sub(r"(\\copyright\s+)\d{4}", r"\g<1>2026", header) + (manual / "header.txt").write_text(header) + return manual + + +def prepare_pdf(documentation_root): + manual = documentation_root / MANUAL + pdf_dir = manual / "build" / "pdf" + pages = json.loads((manual / "build" / "order.json").read_text()) + headers = {} + for page in pages: + staged = pdf_dir / ("Home.md" if page == "index.md" else page) + found = set() + in_fence = False + for line in staged.read_text().splitlines(): + if line.lstrip().startswith(("```", "~~~")): + in_fence = not in_fence + if not in_fence: + match = HEADING.match(line) + if match: + found.add(heading_slug(match.group(2))) + headers[page] = found + + for page in pages: + staged = pdf_dir / ("Home.md" if page == "index.md" else page) + output = [f"[]{{#{page_key(page)}}}\n\n"] + in_fence = False + seen = set() + for line in staged.read_text().splitlines(keepends=True): + anchor = "" + if line.lstrip().startswith(("```", "~~~")): + in_fence = not in_fence + if not in_fence: + match = HEADING.match(line.rstrip("\n")) + if match: + slug = heading_slug(match.group(2)) + unique = slug + counter = 1 + while unique in seen: + counter += 1 + unique = f"{slug}-{counter}" + seen.add(unique) + anchor = f"[]{{#{page_key(page)}-{unique}}}\n\n" + + def rewrite(link): + md = link.group(1) + fragment = link.group(2) + if md is None and fragment is None: + return link.group(0) + target = page if md is None else Path(md).name + if target not in headers: + return link.group(0) + if fragment and fragment not in headers[target]: + raise RuntimeError(f"unresolved PDF link: {page} -> {target}#{fragment}") + anchor = page_key(target) + (f"-{fragment}" if fragment else "") + return f"](#{anchor})" + + line = LINK.sub(rewrite, line) + output.append(anchor + line) + staged.write_text("".join(output)) + + +def main(): + parser = argparse.ArgumentParser(description=__doc__) + parser.add_argument("command", choices=("build", "pdf-links")) + parser.add_argument("--documentation-root", required=True, type=Path) + parser.add_argument("--source-root", type=Path) + parser.add_argument("--target", choices=("all", "html", "pdf"), default="all") + args = parser.parse_args() + documentation_root = args.documentation_root.resolve() + if args.command == "pdf-links": + prepare_pdf(documentation_root) + return + if args.source_root is None: + parser.error("build requires --source-root") + source_root = args.source_root.resolve() + manual = stage(documentation_root, source_root) + subprocess.run( + ["make", "-C", str(manual), "-f", "manual.generated.mk", args.target, + f"WC_SOURCE={source_root}"], + check=True, + ) + + +if __name__ == "__main__": + main()