Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
39 changes: 34 additions & 5 deletions .github/workflows/wolfssl-versions.yml
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,9 @@ jobs:
# bump this workflow every release. Floor (v5.8.0) and master are fixed:
# v5.8.0 is the first release with the public wc_ForceZero symbol and the
# current set of FIPS-204 final ML-DSA APIs wolfCOSE depends on; master
# surfaces upstream drift on the nightly run.
# surfaces upstream drift on the nightly run. Master is tested both classic
# and with ML-DSA/PQC; latest-stable gains an explicit PQC row automatically
# once it is newer than v5.9.1-stable (i.e. when 5.9.2 ships).
discover-versions:
name: Resolve wolfSSL version matrix
runs-on: ubuntu-latest
Expand Down Expand Up @@ -52,17 +54,24 @@ jobs:
LATEST_PQC=false
fi
echo "latest-stable PQC eligible: $LATEST_PQC"
# PQC-able versions (master always; latest-stable once >v5.9.1-stable)
# get an explicit, separately-named ML-DSA row in addition to a
# classic (no-PQC) row, so PQC build+test is always visible and the
# non-PQC build is still exercised on the same wolfSSL.
MATRIX=$(jq -nc --arg latest "$LATEST" --argjson latest_pqc "$LATEST_PQC" '{
include: [
include: ([
{"wolfssl-version":"v5.8.0-stable","wolfssl-ref":"v5.8.0-stable","cache-key":"wolfssl-nopqc-v5.8.0-v1","pqc":false},
{"wolfssl-version":$latest,"wolfssl-ref":$latest,"cache-key":("wolfssl-" + (if $latest_pqc then "pqc" else "nopqc" end) + "-" + $latest + "-v1"),"pqc":$latest_pqc},
{"wolfssl-version":$latest,"wolfssl-ref":$latest,"cache-key":("wolfssl-nopqc-" + $latest + "-v1"),"pqc":false},
{"wolfssl-version":"master","wolfssl-ref":"master","cache-key":"","pqc":false},
{"wolfssl-version":"master","wolfssl-ref":"master","cache-key":"","pqc":true}
]
] + (if $latest_pqc then [
{"wolfssl-version":$latest,"wolfssl-ref":$latest,"cache-key":("wolfssl-pqc-" + $latest + "-v1"),"pqc":true}
] else [] end))
}')
echo "matrix=$MATRIX" >> "$GITHUB_OUTPUT"

wolfssl-version-test:
name: wolfSSL ${{ matrix.wolfssl-version }}
name: wolfSSL ${{ matrix.wolfssl-version }} ${{ matrix.pqc && '(+ML-DSA/PQC)' || '(classic)' }}
needs: discover-versions
runs-on: ubuntu-latest
timeout-minutes: 25
Expand Down Expand Up @@ -133,6 +142,26 @@ jobs:
make tool-test CFLAGS="-std=c99 -DHAVE_ANONYMOUS_INLINE_AGGREGATES=1 -Os -Wall -Wextra -Wpedantic -Wshadow -Wconversion -I./include -isystem $WOLFSSL_DIR/include" \
LDFLAGS="-L$WOLFSSL_DIR/lib -lwolfssl"

# ML-DSA / PQC-specific coverage: CLI keygen->sign->verify for all three
# ML-DSA levels and the ML-DSA sign+verify demo. Runs on the explicit pqc
# rows only, so the row is a clean PQC signal (no classic-alg coupling).
- name: Run ML-DSA PQC tests (CLI round-trip + demo)
if: matrix.pqc
run: |
export WOLFSSL_DIR=$HOME/wolfssl-install
export LD_LIBRARY_PATH=$WOLFSSL_DIR/lib
CF="-std=c99 -DHAVE_ANONYMOUS_INLINE_AGGREGATES=1 -Os -Wall -Wextra -Wpedantic -Wshadow -Wconversion -I./include -isystem $WOLFSSL_DIR/include"
LF="-L$WOLFSSL_DIR/lib -lwolfssl"
make tool CFLAGS="$CF" LDFLAGS="$LF"
echo "wolfCOSE ML-DSA CLI round-trip" > /tmp/pqc-msg.txt
for alg in ML-DSA-44 ML-DSA-65 ML-DSA-87; do
echo "=== $alg CLI keygen -> sign -> verify ==="
./tools/wolfcose_tool keygen -a "$alg" -o /tmp/pqc.key
./tools/wolfcose_tool sign -k /tmp/pqc.key -a "$alg" -i /tmp/pqc-msg.txt -o /tmp/pqc.cose
./tools/wolfcose_tool verify -k /tmp/pqc.key -i /tmp/pqc.cose
done
make mldsa-demo CFLAGS="$CF" LDFLAGS="$LF"

- name: wolfSSL version info
if: always()
run: |
Expand Down
72 changes: 72 additions & 0 deletions ChangeLog.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
# wolfCOSE Release 1.0.0 (release date TBD, after wolfSSL 5.9.2)

Release 1.0.0 is the first stable release of wolfCOSE, a complete,
zero-allocation C implementation of CBOR (RFC 8949) and COSE (RFC 9052/9053)
on top of wolfCrypt. It provides all six COSE message types in both
single-actor and multi-actor forms, 40 algorithms across signing, encryption,
MAC, and key distribution, and standardized post-quantum ML-DSA signatures
(RFC 9964), all heap-allocation-free and within a tiny footprint.

## Vulnerabilities

* None. This is the initial release.

## New Feature Additions

* CBOR engine implementing RFC 8949 encode/decode with no external dependency,
enforcing deterministic/preferred-encoding rules and rejecting non-preferred
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.
* 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.
* 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`
(-1), and the 32-byte seed private key in `priv` (-2).
* `COSE_Key` / `COSE_KeySet` serialization for all supported key types,
including full RFC 8230 RSA private keys (n, e, d, p, q, dP, dQ, qInv).
* Zero dynamic allocation: every operation uses caller-provided buffers, with no
heap, `.data`, or `.bss` usage.
* Path to FIPS 140-3 through wolfCrypt FIPS Certificate #4718 (sole crypto
dependency).
* `WOLFCOSE_LEAN` configuration layer with `WOLFCOSE_HAVE_*` feature gates,
`WOLFCOSE_LEAN_VERIFY` / ML-DSA lean profiles for verify-only targets, and a
`WOLFCOSE_MIN_BUFFERS` bounded-stack profile.
* `LIBWOLFCOSE_VERSION_STRING` / `LIBWOLFCOSE_VERSION_HEX` in
`wolfcose/version.h` for compile-time version checks.

## Fixes

* RSA private `COSE_Key` encode/decode now emits the RFC 8230 MUST-present `dP`
(-6) and `dQ` (-7) CRT exponents and encodes `d` at full modulus width, so a
private RSA key round-trips reliably against strict RSA decoders.

## 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 the
[Footprint](https://github.com/wolfSSL/wolfCOSE/wiki/Footprint) page for
total-flash numbers including wolfCrypt.
* MISRA C:2012 and C:2023 checked.
* CI matrix covering Ubuntu/macOS, GCC 10-14 and Clang 14-18, ~240 algorithm
combination tests, static analysis (cppcheck, Clang analyzer, GCC
`-fanalyzer`), sanitizers (ASan/UBSan), Coverity, a wolfCOSE <-> t_cose
wire-interop conformance suite, and a wolfSSL version matrix with explicit
ML-DSA/PQC rows.

---

wolfCOSE 1.0.0 has been developed according to wolfSSL's development and QA
process (see
https://www.wolfssl.com/about/wolfssl-software-development-process-quality-assurance)
and successfully passed the quality criteria.

For additional vulnerability information visit the vulnerability page at
https://www.wolfssl.com/docs/security-vulnerabilities/

Requires wolfSSL 5.8.0 or later as the crypto backend; ML-DSA support requires
wolfSSL 5.9.2 or later. See README.md for build instructions.
10 changes: 8 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
# wolfCOSE

wolfCOSE is a lightweight C library implementing [CBOR (RFC 8949)](https://www.rfc-editor.org/rfc/rfc8949) and [COSE (RFC 9052/9053)](https://www.rfc-editor.org/rfc/rfc9052) using [wolfSSL](https://www.wolfssl.com/) as the crypto backend.
wolfCOSE is a lightweight C library implementing [CBOR (RFC 8949)](https://www.rfc-editor.org/rfc/rfc8949), [COSE (RFC 9052/9053)](https://www.rfc-editor.org/rfc/rfc9052), and post-quantum [ML-DSA for COSE (RFC 9964)](https://www.rfc-editor.org/rfc/rfc9964) using [wolfSSL](https://www.wolfssl.com/) as the crypto backend.

## Main Features

- **Complete RFC 9052 message set**: all six COSE message types, including multi-signer
`COSE_Sign` and multi-recipient `COSE_Encrypt` / `COSE_Mac`
- **Post-quantum signing**: ML-DSA (FIPS 204) at all three security levels
- **Post-quantum signing**: ML-DSA (FIPS 204) at all three security levels, with RFC 9964 `COSE_Key` (AKP key type, seed-based private keys)
- **40 algorithms** across signing, encryption, MAC, and key distribution
- **Zero dynamic allocation**: heap-allocation-free and non-recursive. Every operation runs on caller-provided buffers
within a bounded, target-customizable stack ceiling (nothing on the heap, zero `.data`/`.bss`)
Expand Down Expand Up @@ -190,6 +190,12 @@ Full documentation is available in the [Wiki](https://github.com/wolfSSL/wolfCOS
- [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

## Release Notes

The current release is **1.0.0**, the first stable release: the complete RFC 9052 COSE message set (all six message types, single- and multi-actor), 40 algorithms, and standardized post-quantum ML-DSA (RFC 9964), all with zero dynamic allocation. See [ChangeLog.md](ChangeLog.md) for the full release notes.

wolfCOSE 1.0.0 has been developed according to wolfSSL's development and QA process (see https://www.wolfssl.com/about/wolfssl-software-development-process-quality-assurance) and successfully passed the quality criteria.

## License

wolfCOSE is free software licensed under [GPLv3](https://www.gnu.org/licenses/gpl-3.0.html); see [LICENSE](LICENSE) for the full text.
Expand Down
32 changes: 32 additions & 0 deletions docs/API-Reference.md
Original file line number Diff line number Diff line change
Expand Up @@ -203,6 +203,10 @@ int wc_CoseKey_SetMlDsa(WOLFCOSE_KEY* key, int32_t alg, wc_MlDsaKey* mlDsaKey);
```

Associate an ML-DSA (FIPS 204) post-quantum key with a COSE key structure.
The key is encoded as an RFC 9964 **AKP** COSE_Key (`kty` = 7, REQUIRED `alg`,
public key in `pub` (-1)). Use this for public-key, sign, and verify use. To
encode a *private* COSE_Key (whose private value is the 32-byte seed), use
`wc_CoseKey_SetMlDsa_ex` and supply the seed.

**Parameters:**
| Name | Description |
Expand All @@ -217,6 +221,34 @@ Associate an ML-DSA (FIPS 204) post-quantum key with a COSE key structure.

---

### wc_CoseKey_SetMlDsa_ex

```c
int wc_CoseKey_SetMlDsa_ex(WOLFCOSE_KEY* key, int32_t alg,
wc_MlDsaKey* mlDsaKey,
const uint8_t* seed, size_t seedLen);
```

Like `wc_CoseKey_SetMlDsa`, but also attaches the 32-byte ML-DSA seed used to
create the key. RFC 9964 represents an ML-DSA private key as the seed, and
wolfCrypt does not retain it, so the caller (who created the key via
`wc_MlDsaKey_MakeKeyFromSeed`) must supply it here to encode a private COSE_Key.

**Parameters:**
| Name | Description |
|------|-------------|
| `key` | Pointer to initialized COSE key |
| `alg` | Algorithm: `WOLFCOSE_ALG_ML_DSA_44`, `WOLFCOSE_ALG_ML_DSA_65`, or `WOLFCOSE_ALG_ML_DSA_87` |
| `mlDsaKey` | Pointer to initialized wolfCrypt ML-DSA key (caller-owned) |
| `seed` | 32-byte ML-DSA seed (caller-owned), or `NULL` for public/sign/verify use |
| `seedLen` | Seed length; must be `WOLFCOSE_MLDSA_SEED_SZ` (32) when `seed` is non-NULL |

**Returns:** `WOLFCOSE_SUCCESS` or error code

**Requires:** `WOLFSSL_HAVE_MLDSA`

---

### wc_CoseKey_SetRsa

```c
Expand Down
7 changes: 6 additions & 1 deletion docs/Algorithms.md
Original file line number Diff line number Diff line change
Expand Up @@ -84,10 +84,15 @@ Used with COSE_Encrypt and COSE_Mac for multi-recipient messages:

| COSE kty | Value | Guard | Algorithms |
|----------|-------|-------|------------|
| OKP | 1 | `HAVE_ED25519` / `HAVE_ED448` / `WOLFSSL_HAVE_MLDSA` | EdDSA, ML-DSA |
| OKP | 1 | `HAVE_ED25519` / `HAVE_ED448` | EdDSA |
| EC2 | 2 | `HAVE_ECC` | ES256, ES384, ES512 |
| RSA | 3 | `WC_RSA_PSS` | PS256, PS384, PS512 |
| Symmetric | 4 | always | AES-GCM, AES-CCM, ChaCha20, HMAC |
| AKP | 7 | `WOLFSSL_HAVE_MLDSA` | ML-DSA (RFC 9964) |

ML-DSA keys use the RFC 9964 **AKP** (Algorithm Key Pair) key type: the `alg`
parameter is REQUIRED, the public key is in `pub` (-1), and the private key is
the 32-byte seed in `priv` (-2). There is no `crv` parameter.

## Curves

Expand Down
5 changes: 4 additions & 1 deletion docs/Getting-Started.md
Original file line number Diff line number Diff line change
Expand Up @@ -228,7 +228,10 @@ int main(void)
wc_MlDsaKey_SetParams(&mlDsaKey, WC_ML_DSA_44);
wc_MlDsaKey_MakeKey(&mlDsaKey, &rng);

/* Wrap in COSE key */
/* Wrap in COSE key. ML-DSA uses the RFC 9964 AKP key type; this is all
* that is needed for sign/verify. To export a *private* COSE_Key, create
* the key with wc_MlDsaKey_MakeKeyFromSeed and pass the 32-byte seed via
* wc_CoseKey_SetMlDsa_ex (RFC 9964 private keys are the seed). */
wc_CoseKey_Init(&coseKey);
wc_CoseKey_SetMlDsa(&coseKey, WOLFCOSE_ALG_ML_DSA_44, &mlDsaKey);

Expand Down
1 change: 1 addition & 0 deletions docs/Home.md
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ It uses [wolfSSL](https://www.wolfssl.com/) as the cryptographic backend and is
| [[Footprint]] | Size and speed numbers, desktop and on-device |
| [[Testing]] | Unit tests, coverage, and failure injection |
| [[Project Structure]] | Source code layout and file descriptions |
| [[Release Notes]] | Per-version changelog and release highlights |

## Supported Message Types

Expand Down
70 changes: 70 additions & 0 deletions docs/Release-Notes.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
# Release Notes

## wolfCOSE 1.0.0 (release date TBD, after wolfSSL 5.9.2)

Release 1.0.0 is the first stable release of wolfCOSE, a complete,
zero-allocation C implementation of CBOR (RFC 8949) and COSE (RFC 9052/9053)
on top of wolfCrypt. It provides all six COSE message types in both
single-actor and multi-actor forms, 40 algorithms across signing, encryption,
MAC, and key distribution, and standardized post-quantum ML-DSA signatures
(RFC 9964), all heap-allocation-free and within a tiny footprint.

### Vulnerabilities

- None. This is the initial release.

### New Feature Additions

- CBOR engine implementing RFC 8949 encode/decode with no external dependency,
enforcing deterministic/preferred-encoding rules and rejecting non-preferred
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]].
- 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]].
- 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`
(-1), and the 32-byte seed private key in `priv` (-2).
- `COSE_Key` / `COSE_KeySet` serialization for all supported key types,
including full RFC 8230 RSA private keys (n, e, d, p, q, dP, dQ, qInv).
- Zero dynamic allocation: every operation uses caller-provided buffers, with no
heap, `.data`, or `.bss` usage.
- Path to FIPS 140-3 through wolfCrypt FIPS Certificate #4718 (sole crypto
dependency).
- `WOLFCOSE_LEAN` configuration layer with `WOLFCOSE_HAVE_*` feature gates,
`WOLFCOSE_LEAN_VERIFY` / ML-DSA lean profiles for verify-only targets, and a
`WOLFCOSE_MIN_BUFFERS` bounded-stack profile. See [[Macros]].
- `LIBWOLFCOSE_VERSION_STRING` / `LIBWOLFCOSE_VERSION_HEX` in
`wolfcose/version.h` for compile-time version checks.

### Fixes

- RSA private `COSE_Key` encode/decode now emits the RFC 8230 MUST-present `dP`
(-6) and `dQ` (-7) CRT exponents and encodes `d` at full modulus width, so a
private RSA key round-trips reliably against strict RSA decoders.

### 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]].
- CI matrix covering Ubuntu/macOS, GCC 10-14 and Clang 14-18, ~240 algorithm
combination tests, static analysis (cppcheck, Clang analyzer, GCC
`-fanalyzer`), sanitizers (ASan/UBSan), Coverity, a wolfCOSE <-> t_cose
wire-interop conformance suite, and a wolfSSL version matrix with explicit
ML-DSA/PQC rows. See [[Testing]].

---

wolfCOSE 1.0.0 has been developed according to wolfSSL's development and QA
process (see the [wolfSSL Software Development Process and Quality
Assurance](https://www.wolfssl.com/about/wolfssl-software-development-process-quality-assurance)
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.
1 change: 1 addition & 0 deletions docs/_Sidebar.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,3 +10,4 @@
- [[Testing]]
- [[MISRA Compliance]]
- [[Project Structure]]
- [[Release Notes]]
5 changes: 3 additions & 2 deletions include/wolfcose/settings.h
Original file line number Diff line number Diff line change
Expand Up @@ -473,9 +473,10 @@ extern "C" {
#endif
#ifndef WOLFCOSE_MAX_MAP_ITEMS
#if defined(WOLFCOSE_MIN_BUFFERS)
/* Full private RSA key = 9 entries (kty,n,e,d,p,q,qInv,kid,alg). */
#if defined(WOLFCOSE_HAVE_RSAPSS)
#define WOLFCOSE_MAX_MAP_ITEMS 9u
/* Full private RSA key = 11 entries
* (kty,n,e,d,p,q,dP,dQ,qInv,kid,alg) per RFC 8230. */
#define WOLFCOSE_MAX_MAP_ITEMS 11u
#else
#define WOLFCOSE_MAX_MAP_ITEMS 8u
#endif
Expand Down
35 changes: 35 additions & 0 deletions include/wolfcose/version.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
/* version.h
*
* Copyright (C) 2026 wolfSSL Inc.
*
* This file is part of wolfCOSE.
*
* wolfCOSE is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* wolfCOSE is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, see <https://www.gnu.org/licenses/>.
*/

#ifndef WOLFCOSE_VERSION_H
#define WOLFCOSE_VERSION_H

#ifdef __cplusplus
extern "C" {
#endif

#define LIBWOLFCOSE_VERSION_STRING "1.0.0"
#define LIBWOLFCOSE_VERSION_HEX 0x01000000

#ifdef __cplusplus
}
#endif

#endif /* WOLFCOSE_VERSION_H */
Loading
Loading