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

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 7 additions & 3 deletions .github/workflows/minimal-build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,10 @@ jobs:
- name: MAC-only (HMAC + AES-MAC)
wolfssl_flags: "--enable-cryptonly --enable-sha256 --enable-sha384 --enable-sha512 --enable-aescbc"
cache_key: wolfssl-mac-only-v1
- name: Lean core (WOLFCOSE_LEAN, minimal wolfSSL)
wolfssl_flags: "--enable-cryptonly --enable-ecc --enable-aesgcm --enable-keygen"
cache_key: wolfssl-ecc-only-v4
cose_flags: "-DWOLFCOSE_LEAN"

steps:
- uses: actions/checkout@v4
Expand Down Expand Up @@ -81,19 +85,19 @@ jobs:
- name: Build wolfCOSE
run: |
export WOLFSSL_DIR=$HOME/wolfssl-minimal
make CFLAGS="-std=c99 -DHAVE_ANONYMOUS_INLINE_AGGREGATES=1 -Os -Wall -Wextra -Wpedantic -Wshadow -Wconversion -I./include -isystem $WOLFSSL_DIR/include" \
make CFLAGS="-std=c99 -DHAVE_ANONYMOUS_INLINE_AGGREGATES=1 -Os -Wall -Wextra -Wpedantic -Wshadow -Wconversion ${{ matrix.cose_flags }} -I./include -isystem $WOLFSSL_DIR/include" \
LDFLAGS="-L$WOLFSSL_DIR/lib -lwolfssl"
- name: Run unit tests
run: |
export WOLFSSL_DIR=$HOME/wolfssl-minimal
export LD_LIBRARY_PATH=$WOLFSSL_DIR/lib
make test CFLAGS="-std=c99 -DHAVE_ANONYMOUS_INLINE_AGGREGATES=1 -Os -Wall -Wextra -Wpedantic -Wshadow -Wconversion -I./include -isystem $WOLFSSL_DIR/include" \
make test CFLAGS="-std=c99 -DHAVE_ANONYMOUS_INLINE_AGGREGATES=1 -Os -Wall -Wextra -Wpedantic -Wshadow -Wconversion ${{ matrix.cose_flags }} -I./include -isystem $WOLFSSL_DIR/include" \
LDFLAGS="-L$WOLFSSL_DIR/lib -lwolfssl"
- name: Run tool round-trip test
run: |
export WOLFSSL_DIR=$HOME/wolfssl-minimal
export LD_LIBRARY_PATH=$WOLFSSL_DIR/lib
make tool-test CFLAGS="-std=c99 -DHAVE_ANONYMOUS_INLINE_AGGREGATES=1 -Os -Wall -Wextra -Wpedantic -Wshadow -Wconversion -I./include -isystem $WOLFSSL_DIR/include" \
make tool-test CFLAGS="-std=c99 -DHAVE_ANONYMOUS_INLINE_AGGREGATES=1 -Os -Wall -Wextra -Wpedantic -Wshadow -Wconversion ${{ matrix.cose_flags }} -I./include -isystem $WOLFSSL_DIR/include" \
LDFLAGS="-L$WOLFSSL_DIR/lib -lwolfssl"
10 changes: 0 additions & 10 deletions .github/workflows/misra-2023.yml
Original file line number Diff line number Diff line change
Expand Up @@ -100,16 +100,6 @@ jobs:
-DWOLFSSL_SHA384 -DWOLFSSL_SHA512 \
-DHAVE_AES_KEYWRAP -DWOLFSSL_AES_DIRECT \
-DHAVE_HKDF -DHAVE_AES_CBC \
-DWOLFCOSE_SIGN1 -DWOLFCOSE_SIGN1_SIGN -DWOLFCOSE_SIGN1_VERIFY \
-DWOLFCOSE_ENCRYPT0 -DWOLFCOSE_ENCRYPT0_ENCRYPT -DWOLFCOSE_ENCRYPT0_DECRYPT \
-DWOLFCOSE_MAC0 -DWOLFCOSE_MAC0_CREATE -DWOLFCOSE_MAC0_VERIFY \
-DWOLFCOSE_SIGN -DWOLFCOSE_SIGN_SIGN -DWOLFCOSE_SIGN_VERIFY \
-DWOLFCOSE_ENCRYPT -DWOLFCOSE_ENCRYPT_ENCRYPT -DWOLFCOSE_ENCRYPT_DECRYPT \
-DWOLFCOSE_MAC -DWOLFCOSE_MAC_CREATE -DWOLFCOSE_MAC_VERIFY \
-DWOLFCOSE_RECIPIENTS -DWOLFCOSE_KEY_WRAP \
-DWOLFCOSE_ECDH -DWOLFCOSE_ECDH_WRAP \
-DWOLFCOSE_CBOR_ENCODE -DWOLFCOSE_CBOR_DECODE \
-DWOLFCOSE_KEY_ENCODE -DWOLFCOSE_KEY_DECODE \
-DWOLFCOSE_FLOAT \
-I./include -isystem $WOLFSSL_DIR/include"
for f in src/*.c; do
Expand Down
54 changes: 43 additions & 11 deletions docs/Macros.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,41 @@
# Configuration Macros

wolfCOSE uses an opt-out design: all features are enabled by default, and you disable the ones you don't need with `WOLFCOSE_NO_*` defines. A more configurable model — opt-in tuning via `user_settings.h` for features that should not be on by default — is on the roadmap.
wolfCOSE has two configuration modes. The default is an opt-out full build: every algorithm wolfSSL provides is enabled, and you strip what you don't need with `WOLFCOSE_NO_*` defines. Alternatively, `WOLFCOSE_LEAN` switches to an opt-in core build and you add extensions with `WOLFCOSE_ENABLE_*`. See [Lean Configuration Layer](#lean-configuration-layer).

## Lean Configuration Layer

Defining `WOLFCOSE_LEAN` keeps only the core — `COSE_Sign1`/`Encrypt0`/`Mac0` with ES256, AES-GCM, and HMAC-SHA256 — and turns every other algorithm into an opt-in. This is the recommended starting point for constrained targets.

| Define | Description |
|--------|-------------|
| `WOLFCOSE_LEAN` | Core-only base; all extensions become opt-in |
| `WOLFCOSE_ENABLE_ALL` | Re-enable every extension on top of `WOLFCOSE_LEAN` |
| `WOLFCOSE_ENABLE_<X>` | Opt in a single extension (see list below) |

Extension names for `WOLFCOSE_ENABLE_<X>`: `ES384`, `ES512`, `EDDSA`, `ED448`, `RSAPSS`, `MLDSA`, `HMAC384`, `HMAC512`, `AESCCM`, `CHACHA20`, `AESMAC`, `AESWRAP`, `ECDH_ES`, `SIGN` (multi-signer), `ENCRYPT` (multi-recipient), `MAC` (multi-recipient).

An extension is compiled in when it is explicitly enabled (`WOLFCOSE_ENABLE_<X>` or `WOLFCOSE_ENABLE_ALL`), or — in a non-lean build — when wolfSSL provides the primitive and it is not opted out with `WOLFCOSE_NO_<X>`. Enabling an extension wolfSSL cannot provide is a compile error. The resolved state is exposed internally as read-only `WOLFCOSE_HAVE_<X>` gates (e.g. `WOLFCOSE_HAVE_MLDSA`); sources, tests, and examples compile against those, so you set `WOLFCOSE_ENABLE_*`/`WOLFCOSE_NO_*`, not `WOLFCOSE_HAVE_*`.

## Algorithm Gates

Per-algorithm opt-outs for the default (non-lean) build. Each also has a `WOLFCOSE_ENABLE_<X>` form for lean opt-in. `ES256`, `AESGCM`, and `HMAC256` form the lean core and stay on unless explicitly opted out.

| Opt-out | Algorithm | wolfSSL requirement |
|---------|-----------|---------------------|
| `WOLFCOSE_NO_ES256` | ECDSA P-256 (ES256) | `HAVE_ECC` |
| `WOLFCOSE_NO_ES384` | ECDSA P-384 (ES384) | `HAVE_ECC` + `WOLFSSL_SHA384` |
| `WOLFCOSE_NO_ES512` | ECDSA P-521 (ES512) | `HAVE_ECC` + `WOLFSSL_SHA512` |
| `WOLFCOSE_NO_EDDSA` | Ed25519 | `HAVE_ED25519` |
| `WOLFCOSE_NO_ED448` | Ed448 | `HAVE_ED448` |
| `WOLFCOSE_NO_RSAPSS` | RSA-PSS (PS256/384/512) | `WC_RSA_PSS` |
| `WOLFCOSE_NO_MLDSA` | ML-DSA (FIPS 204) | `WOLFSSL_HAVE_MLDSA` |
| `WOLFCOSE_NO_AESGCM` | AES-GCM | `HAVE_AESGCM` |
| `WOLFCOSE_NO_AESCCM` | AES-CCM | `HAVE_AESCCM` |
| `WOLFCOSE_NO_CHACHA20` | ChaCha20-Poly1305 | `HAVE_CHACHA` + `HAVE_POLY1305` |
| `WOLFCOSE_NO_HMAC256` | HMAC-SHA256 | HMAC (`NO_HMAC` unset) |
| `WOLFCOSE_NO_HMAC384` | HMAC-SHA384 | `WOLFSSL_SHA384` |
| `WOLFCOSE_NO_HMAC512` | HMAC-SHA512 | `WOLFSSL_SHA512` |
| `WOLFCOSE_NO_AESMAC` | AES-CBC-MAC | `HAVE_AES_CBC` |

## Message Type Gates

Expand Down Expand Up @@ -76,16 +111,13 @@ wolfCOSE uses an opt-out design: all features are enabled by default, and you di

| Define | Description | Default |
|--------|-------------|---------|
| `WOLFCOSE_RECIPIENTS` | Enable recipient array support | Enabled |
| `WOLFCOSE_NO_RECIPIENTS` | Disable all multi-recipient support | - |
| `WOLFCOSE_KEY_WRAP` | Enable AES Key Wrap (A128KW, A192KW, A256KW) | Enabled* |
| `WOLFCOSE_NO_KEY_WRAP` | Disable AES Key Wrap | - |
| `WOLFCOSE_ECDH` | Enable ECDH key distribution | Enabled* |
| `WOLFCOSE_NO_ECDH` | Disable ECDH | - |
| `WOLFCOSE_ECDH_WRAP` | Enable ECDH-ES + AES-KW combined modes | Enabled* |
| `WOLFCOSE_NO_ECDH_WRAP` | Disable ECDH + wrap | - |

*Requires corresponding wolfSSL feature enabled (`HAVE_AES_KEYWRAP`, `HAVE_ECC`)
| `WOLFCOSE_NO_RECIPIENTS` | Disable all multi-recipient support (COSE_Encrypt/COSE_Mac) | - |
| `WOLFCOSE_NO_AESWRAP` | Disable AES Key Wrap (A128KW, A192KW, A256KW) | - |
| `WOLFCOSE_NO_ECDH_ES` | Disable ECDH-ES key agreement | - |
| `WOLFCOSE_ENABLE_AESWRAP` | Opt in AES Key Wrap under `WOLFCOSE_LEAN` | - |
| `WOLFCOSE_ENABLE_ECDH_ES` | Opt in ECDH-ES under `WOLFCOSE_LEAN` | - |

Resolved internally as read-only `WOLFCOSE_KEY_WRAP`, `WOLFCOSE_ECDH`, and `WOLFCOSE_ECDH_WRAP` gates. Requires the matching wolfSSL feature (`HAVE_AES_KEYWRAP`; `HAVE_ECC` + `HAVE_HKDF` for ECDH-ES) and at least one multi-recipient message type enabled.

---

Expand Down
32 changes: 16 additions & 16 deletions examples/comprehensive/encrypt_all.c
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@
* @param useAad 0=no AAD, 1=with external AAD
* @return 0 on success, negative error code on failure.
*/
#ifdef HAVE_AESGCM
#ifdef WOLFCOSE_HAVE_AESGCM
static int test_encrypt0(int32_t alg, int keySz, int detached, int useAad)
{
int ret = 0;
Expand Down Expand Up @@ -164,10 +164,10 @@ static int test_encrypt0(int32_t alg, int keySz, int detached, int useAad)

return ret;
}
#endif /* HAVE_AESGCM */
#endif /* WOLFCOSE_HAVE_AESGCM */

/* ----- Multi-Recipient Encrypt Worker (Direct Key) ----- */
#if defined(HAVE_AESGCM) && defined(WOLFCOSE_ENCRYPT)
#if defined(WOLFCOSE_HAVE_AESGCM) && defined(WOLFCOSE_ENCRYPT)
static int test_encrypt_multi_direct(int32_t contentAlg, int keySz,
int recipCount, int detached, int useAad)
{
Expand Down Expand Up @@ -255,10 +255,10 @@ static int test_encrypt_multi_direct(int32_t contentAlg, int keySz,
}
return ret;
}
#endif /* HAVE_AESGCM && WOLFCOSE_ENCRYPT */
#endif /* WOLFCOSE_HAVE_AESGCM && WOLFCOSE_ENCRYPT */

/* ----- Multi-Recipient with Different Keys (Wrong Key Test) ----- */
#if defined(HAVE_AESGCM) && defined(WOLFCOSE_ENCRYPT)
#if defined(WOLFCOSE_HAVE_AESGCM) && defined(WOLFCOSE_ENCRYPT)
static int test_encrypt_wrong_key(void)
{
int ret = 0;
Expand Down Expand Up @@ -365,10 +365,10 @@ static int test_encrypt_wrong_key(void)
}
return ret;
}
#endif /* HAVE_AESGCM && WOLFCOSE_ENCRYPT */
#endif /* WOLFCOSE_HAVE_AESGCM && WOLFCOSE_ENCRYPT */

/* ----- Encrypt0 Test Runner (12 tests) ----- */
#ifdef HAVE_AESGCM
#ifdef WOLFCOSE_HAVE_AESGCM
static int test_encrypt0_all(void)
{
int ret = 0;
Expand Down Expand Up @@ -437,10 +437,10 @@ static int test_encrypt0_all(void)
printf("\nEncrypt0 Summary: %d passed, %d failed\n", passed, failed);
return failed;
}
#endif /* HAVE_AESGCM */
#endif /* WOLFCOSE_HAVE_AESGCM */

/* ----- Multi-Recipient Test Runner ----- */
#if defined(HAVE_AESGCM) && defined(WOLFCOSE_ENCRYPT) && \
#if defined(WOLFCOSE_HAVE_AESGCM) && defined(WOLFCOSE_ENCRYPT) && \
!defined(WOLFCOSE_NO_ENCRYPT_ALL_MULTI)
static int test_encrypt_multi_all(void)
{
Expand Down Expand Up @@ -500,10 +500,10 @@ static int test_encrypt_multi_all(void)
printf("\nMulti-Recipient Summary: %d passed, %d failed\n", passed, failed);
return failed;
}
#endif /* HAVE_AESGCM && WOLFCOSE_ENCRYPT */
#endif /* WOLFCOSE_HAVE_AESGCM && WOLFCOSE_ENCRYPT */

/* ----- Interop Vector Tests ----- */
#if defined(HAVE_AESGCM) && !defined(WOLFCOSE_NO_ENCRYPT_ALL_INTEROP)
#if defined(WOLFCOSE_HAVE_AESGCM) && !defined(WOLFCOSE_NO_ENCRYPT_ALL_INTEROP)
static int test_encrypt0_interop(void)
{
int ret = 0;
Expand Down Expand Up @@ -576,7 +576,7 @@ static int test_encrypt0_interop(void)
printf("\nInterop Summary: %d passed, %d failed\n", passed, failed);
return failed;
}
#endif /* HAVE_AESGCM && !WOLFCOSE_NO_ENCRYPT_ALL_INTEROP */
#endif /* WOLFCOSE_HAVE_AESGCM && !WOLFCOSE_NO_ENCRYPT_ALL_INTEROP */

/* ----- Main Entry Point ----- */
int main(void)
Expand All @@ -587,20 +587,20 @@ int main(void)
printf("wolfCOSE Comprehensive Encrypt Tests\n");
printf("========================================\n");

#ifdef HAVE_AESGCM
#ifdef WOLFCOSE_HAVE_AESGCM
totalFailed += test_encrypt0_all();
#endif

#if defined(HAVE_AESGCM) && defined(WOLFCOSE_ENCRYPT) && \
#if defined(WOLFCOSE_HAVE_AESGCM) && defined(WOLFCOSE_ENCRYPT) && \
!defined(WOLFCOSE_NO_ENCRYPT_ALL_MULTI)
totalFailed += test_encrypt_multi_all();
#endif

#if defined(HAVE_AESGCM) && !defined(WOLFCOSE_NO_ENCRYPT_ALL_INTEROP)
#if defined(WOLFCOSE_HAVE_AESGCM) && !defined(WOLFCOSE_NO_ENCRYPT_ALL_INTEROP)
totalFailed += test_encrypt0_interop();
#endif

#ifndef HAVE_AESGCM
#ifndef WOLFCOSE_HAVE_AESGCM
printf("AES-GCM not available - encryption tests skipped\n");
#endif

Expand Down
Loading
Loading