diff --git a/.github/workflows/wiki-sync.yml b/.github/workflows/wiki-sync.yml new file mode 100644 index 0000000..9938adb --- /dev/null +++ b/.github/workflows/wiki-sync.yml @@ -0,0 +1,26 @@ +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 + +jobs: + sync: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - name: Publish docs/ to wiki + uses: Andrew-Chen-Wang/github-wiki-action@50650fccf3a10f741995523cf9708c53cec8912a # v4 + with: + path: docs/ diff --git a/docs/API-Reference.md b/docs/API-Reference.md new file mode 100644 index 0000000..edd15aa --- /dev/null +++ b/docs/API-Reference.md @@ -0,0 +1,752 @@ +# API Reference + +Complete API documentation for wolfCOSE (RFC 9052/9053 COSE implementation). + +## Table of Contents + +- [Data Structures](#data-structures) +- [COSE_Key API](#cose_key-api) +- [COSE_Sign1 API](#cose_sign1-api) +- [COSE_Encrypt0 API](#cose_encrypt0-api) +- [COSE_Mac0 API](#cose_mac0-api) +- [COSE_Sign API (Multi-Signer)](#cose_sign-api-multi-signer) +- [COSE_Encrypt API (Multi-Recipient)](#cose_encrypt-api-multi-recipient) +- [COSE_Mac API (Multi-Recipient)](#cose_mac-api-multi-recipient) +- [CBOR API](#cbor-api) +- [Error Codes](#error-codes) + +--- + +## Data Structures + +### WOLFCOSE_KEY + +```c +typedef struct WOLFCOSE_KEY { + int32_t kty; /* Key type: WOLFCOSE_KTY_EC2, WOLFCOSE_KTY_OKP, etc. */ + int32_t alg; /* Algorithm hint (optional) */ + int32_t crv; /* Curve for EC2/OKP keys */ + union { + ecc_key* ecc; + ed25519_key* ed25519; + ed448_key* ed448; + RsaKey* rsa; + wc_MlDsaKey* mldsa; + struct { + const uint8_t* key; + size_t keyLen; + } symm; + } key; +} WOLFCOSE_KEY; +``` + +Pointer-based key structure (~48 bytes). Caller owns underlying wolfCrypt keys. + +--- + +### WOLFCOSE_HDR + +```c +typedef struct WOLFCOSE_HDR { + int32_t alg; /* Algorithm from protected header */ + const uint8_t* kid; /* Key ID (zero-copy pointer) */ + size_t kidLen; + const uint8_t* iv; /* IV from unprotected header */ + size_t ivLen; + uint8_t flags; /* WOLFCOSE_HDR_FLAG_* */ +} WOLFCOSE_HDR; +``` + +Parsed COSE header information. + +--- + +### WOLFCOSE_SIGNATURE + +```c +typedef struct WOLFCOSE_SIGNATURE { + int32_t algId; /* Signature algorithm */ + WOLFCOSE_KEY* key; /* Signing key */ + const uint8_t* kid; /* Key identifier */ + size_t kidLen; +} WOLFCOSE_SIGNATURE; +``` + +Signer information for COSE_Sign multi-signer messages. + +--- + +### WOLFCOSE_RECIPIENT + +```c +typedef struct WOLFCOSE_RECIPIENT { + int32_t algId; /* Key distribution algorithm */ + WOLFCOSE_KEY* key; /* Recipient key */ + const uint8_t* kid; /* Key identifier */ + size_t kidLen; +} WOLFCOSE_RECIPIENT; +``` + +Recipient information for COSE_Encrypt and COSE_Mac multi-recipient messages. + +--- + +### WOLFCOSE_CBOR_CTX + +```c +typedef struct WOLFCOSE_CBOR_CTX { + uint8_t* buf; /* Buffer pointer */ + size_t bufSz; /* Buffer size */ + size_t idx; /* Current position */ +} WOLFCOSE_CBOR_CTX; +``` + +CBOR encoder/decoder context. + +--- + +## COSE_Key API + +### wc_CoseKey_Init + +```c +int wc_CoseKey_Init(WOLFCOSE_KEY* key); +``` + +Initialize a COSE key structure. + +**Parameters:** +| Name | Description | +|------|-------------| +| `key` | Pointer to COSE key structure to initialize | + +**Returns:** `WOLFCOSE_SUCCESS` (0) or `WOLFCOSE_E_INVALID_ARG` + +--- + +### wc_CoseKey_Free + +```c +void wc_CoseKey_Free(WOLFCOSE_KEY* key); +``` + +Free a COSE key structure. Does NOT free the underlying wolfCrypt key (caller owns key lifecycle). + +**Parameters:** +| Name | Description | +|------|-------------| +| `key` | Pointer to COSE key structure to free | + +--- + +### wc_CoseKey_SetEcc + +```c +int wc_CoseKey_SetEcc(WOLFCOSE_KEY* key, int32_t crv, ecc_key* eccKey); +``` + +Associate an ECC key with a COSE key structure. + +**Parameters:** +| Name | Description | +|------|-------------| +| `key` | Pointer to initialized COSE key | +| `crv` | Curve identifier: `WOLFCOSE_CRV_P256`, `WOLFCOSE_CRV_P384`, or `WOLFCOSE_CRV_P521` | +| `eccKey` | Pointer to initialized wolfCrypt ECC key (caller-owned) | + +**Returns:** `WOLFCOSE_SUCCESS` or error code + +--- + +### wc_CoseKey_SetEd25519 + +```c +int wc_CoseKey_SetEd25519(WOLFCOSE_KEY* key, ed25519_key* edKey); +``` + +Associate an Ed25519 key with a COSE key structure. + +**Parameters:** +| Name | Description | +|------|-------------| +| `key` | Pointer to initialized COSE key | +| `edKey` | Pointer to initialized wolfCrypt Ed25519 key (caller-owned) | + +**Returns:** `WOLFCOSE_SUCCESS` or error code + +--- + +### wc_CoseKey_SetEd448 + +```c +int wc_CoseKey_SetEd448(WOLFCOSE_KEY* key, ed448_key* edKey); +``` + +Associate an Ed448 key with a COSE key structure. + +**Parameters:** +| Name | Description | +|------|-------------| +| `key` | Pointer to initialized COSE key | +| `edKey` | Pointer to initialized wolfCrypt Ed448 key (caller-owned) | + +**Returns:** `WOLFCOSE_SUCCESS` or error code + +**Requires:** `HAVE_ED448` + +--- + +### wc_CoseKey_SetMlDsa + +```c +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. + +**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) | + +**Returns:** `WOLFCOSE_SUCCESS` or error code + +**Requires:** `WOLFSSL_HAVE_MLDSA` + +--- + +### wc_CoseKey_SetRsa + +```c +int wc_CoseKey_SetRsa(WOLFCOSE_KEY* key, RsaKey* rsaKey); +``` + +Associate an RSA key with a COSE key structure. + +**Parameters:** +| Name | Description | +|------|-------------| +| `key` | Pointer to initialized COSE key | +| `rsaKey` | Pointer to initialized wolfCrypt RSA key (caller-owned) | + +**Returns:** `WOLFCOSE_SUCCESS` or error code + +**Requires:** `WC_RSA_PSS` + +--- + +### wc_CoseKey_SetSymmetric + +```c +int wc_CoseKey_SetSymmetric(WOLFCOSE_KEY* key, const uint8_t* keyData, size_t keyLen); +``` + +Set symmetric key material in a COSE key structure. + +**Parameters:** +| Name | Description | +|------|-------------| +| `key` | Pointer to initialized COSE key | +| `keyData` | Pointer to symmetric key bytes (caller-owned buffer) | +| `keyLen` | Length of key in bytes (16, 24, or 32 for AES-GCM) | + +**Returns:** `WOLFCOSE_SUCCESS` or error code + +--- + +### wc_CoseKey_Encode + +```c +int wc_CoseKey_Encode(const WOLFCOSE_KEY* key, uint8_t* buf, size_t bufSz, size_t* outLen); +``` + +Encode a COSE key to CBOR format. + +**Parameters:** +| Name | Description | +|------|-------------| +| `key` | Pointer to COSE key to encode | +| `buf` | Output buffer | +| `bufSz` | Size of output buffer | +| `outLen` | Receives actual encoded length | + +**Returns:** `WOLFCOSE_SUCCESS` or error code + +--- + +### wc_CoseKey_Decode + +```c +int wc_CoseKey_Decode(WOLFCOSE_KEY* key, const uint8_t* buf, size_t bufSz); +``` + +Decode a COSE key from CBOR format. + +**Parameters:** +| Name | Description | +|------|-------------| +| `key` | Pointer to COSE key structure (with pre-allocated wolfCrypt key) | +| `buf` | Input CBOR buffer | +| `bufSz` | Size of input buffer | + +**Returns:** `WOLFCOSE_SUCCESS` or error code + +--- + +## COSE_Sign1 API + +### wc_CoseSign1_Sign + +```c +int wc_CoseSign1_Sign( + const WOLFCOSE_KEY* key, + int32_t alg, + const uint8_t* kid, size_t kidLen, + const uint8_t* payload, size_t payloadLen, + const uint8_t* detachedPayload, size_t detachedPayloadLen, + const uint8_t* extAad, size_t extAadLen, + uint8_t* scratch, size_t scratchSz, + uint8_t* out, size_t outSz, size_t* outLen, + WC_RNG* rng +); +``` + +Create a COSE_Sign1 message (single signer). + +**Parameters:** +| Name | Description | +|------|-------------| +| `key` | Signing key (must have private key) | +| `alg` | Algorithm: `WOLFCOSE_ALG_ES256`, `WOLFCOSE_ALG_ES384`, `WOLFCOSE_ALG_ES512`, `WOLFCOSE_ALG_EDDSA`, etc. | +| `kid`, `kidLen` | Optional key identifier | +| `payload`, `payloadLen` | Payload to include in message (or NULL for detached) | +| `detachedPayload`, `detachedPayloadLen` | Payload to sign but not include | +| `extAad`, `extAadLen` | External additional authenticated data | +| `scratch`, `scratchSz` | Scratch buffer (min `WOLFCOSE_MAX_SCRATCH_SZ`) | +| `out`, `outSz`, `outLen` | Output buffer and length | +| `rng` | Random number generator for ECDSA | + +**Returns:** `WOLFCOSE_SUCCESS` or error code + +--- + +### wc_CoseSign1_Verify + +```c +int wc_CoseSign1_Verify( + const WOLFCOSE_KEY* key, + const uint8_t* coseMsg, size_t coseMsgLen, + const uint8_t* detachedPayload, size_t detachedPayloadLen, + const uint8_t* extAad, size_t extAadLen, + uint8_t* scratch, size_t scratchSz, + WOLFCOSE_HDR* hdr, + const uint8_t** payload, size_t* payloadLen +); +``` + +Verify a COSE_Sign1 message and extract payload. + +**Parameters:** +| Name | Description | +|------|-------------| +| `key` | Verification key (public key sufficient) | +| `coseMsg`, `coseMsgLen` | COSE_Sign1 message to verify | +| `detachedPayload`, `detachedPayloadLen` | Detached payload (if message has null payload) | +| `extAad`, `extAadLen` | External AAD (must match what was used during signing) | +| `scratch`, `scratchSz` | Scratch buffer | +| `hdr` | Receives parsed header information | +| `payload`, `payloadLen` | Receives pointer to payload (zero-copy into coseMsg) | + +**Returns:** `WOLFCOSE_SUCCESS`, `WOLFCOSE_E_COSE_SIG_FAIL`, or other error + +--- + +## COSE_Encrypt0 API + +### wc_CoseEncrypt0_Encrypt + +```c +int wc_CoseEncrypt0_Encrypt( + const WOLFCOSE_KEY* key, + int32_t alg, + const uint8_t* iv, size_t ivLen, + const uint8_t* payload, size_t payloadLen, + uint8_t* detachedCt, size_t detachedCtSz, size_t* detachedCtLen, + const uint8_t* extAad, size_t extAadLen, + uint8_t* scratch, size_t scratchSz, + uint8_t* out, size_t outSz, size_t* outLen +); +``` + +Create a COSE_Encrypt0 message. + +**Parameters:** +| Name | Description | +|------|-------------| +| `key` | Symmetric encryption key | +| `alg` | Algorithm: `WOLFCOSE_ALG_A128GCM`, `WOLFCOSE_ALG_A192GCM`, `WOLFCOSE_ALG_A256GCM`, etc. | +| `iv`, `ivLen` | Initialization vector (12 bytes for AES-GCM) | +| `payload`, `payloadLen` | Plaintext to encrypt | +| `detachedCt`, `detachedCtSz`, `detachedCtLen` | Optional: receive ciphertext separately | +| `extAad`, `extAadLen` | External additional authenticated data | +| `scratch`, `scratchSz` | Scratch buffer | +| `out`, `outSz`, `outLen` | Output buffer and length | + +**Returns:** `WOLFCOSE_SUCCESS` or error code + +--- + +### wc_CoseEncrypt0_Decrypt + +```c +int wc_CoseEncrypt0_Decrypt( + const WOLFCOSE_KEY* key, + const uint8_t* coseMsg, size_t coseMsgLen, + const uint8_t* detachedCt, size_t detachedCtLen, + const uint8_t* extAad, size_t extAadLen, + uint8_t* scratch, size_t scratchSz, + WOLFCOSE_HDR* hdr, + uint8_t* plaintext, size_t plaintextSz, size_t* plaintextLen +); +``` + +Decrypt a COSE_Encrypt0 message. + +**Parameters:** +| Name | Description | +|------|-------------| +| `key` | Symmetric decryption key | +| `coseMsg`, `coseMsgLen` | COSE_Encrypt0 message | +| `detachedCt`, `detachedCtLen` | Detached ciphertext (if message has null ciphertext) | +| `extAad`, `extAadLen` | External AAD (must match encryption) | +| `scratch`, `scratchSz` | Scratch buffer | +| `hdr` | Receives parsed header information | +| `plaintext`, `plaintextSz`, `plaintextLen` | Output buffer for decrypted data | + +**Returns:** `WOLFCOSE_SUCCESS`, `WOLFCOSE_E_COSE_DECRYPT_FAIL`, or other error + +--- + +## COSE_Mac0 API + +### wc_CoseMac0_Create + +```c +int wc_CoseMac0_Create( + WOLFCOSE_KEY* key, + int32_t alg, + const uint8_t* kid, size_t kidLen, + const uint8_t* payload, size_t payloadLen, + const uint8_t* detachedPayload, size_t detachedPayloadLen, + const uint8_t* extAad, size_t extAadLen, + uint8_t* scratch, size_t scratchSz, + uint8_t* out, size_t outSz, size_t* outLen +); +``` + +Create a COSE_Mac0 message. + +**Parameters:** +| Name | Description | +|------|-------------| +| `key` | Symmetric MAC key | +| `alg` | Algorithm: `WOLFCOSE_ALG_HMAC_256_256`, `WOLFCOSE_ALG_AES_MAC_128_64`, etc. | +| `kid`, `kidLen` | Key identifier (can be NULL, 0) | +| `payload`, `payloadLen` | Payload to include in message | +| `detachedPayload`, `detachedPayloadLen` | Payload to MAC but not include | +| `extAad`, `extAadLen` | External AAD | +| `scratch`, `scratchSz` | Scratch buffer | +| `out`, `outSz`, `outLen` | Output buffer and length | + +**Returns:** `WOLFCOSE_SUCCESS` or error code + +--- + +### wc_CoseMac0_Verify + +```c +int wc_CoseMac0_Verify( + const WOLFCOSE_KEY* key, + const uint8_t* coseMsg, size_t coseMsgLen, + const uint8_t* detachedPayload, size_t detachedPayloadLen, + const uint8_t* extAad, size_t extAadLen, + uint8_t* scratch, size_t scratchSz, + WOLFCOSE_HDR* hdr, + const uint8_t** payload, size_t* payloadLen +); +``` + +Verify a COSE_Mac0 message. + +**Parameters:** +| Name | Description | +|------|-------------| +| `key` | Symmetric MAC key | +| `coseMsg`, `coseMsgLen` | COSE_Mac0 message | +| `detachedPayload`, `detachedPayloadLen` | Detached payload if applicable | +| `extAad`, `extAadLen` | External AAD | +| `scratch`, `scratchSz` | Scratch buffer | +| `hdr` | Receives parsed header | +| `payload`, `payloadLen` | Receives payload pointer | + +**Returns:** `WOLFCOSE_SUCCESS`, `WOLFCOSE_E_MAC_FAIL`, or other error + +--- + +## COSE_Sign API (Multi-Signer) + +### wc_CoseSign_Sign + +```c +int wc_CoseSign_Sign( + const WOLFCOSE_SIGNATURE* signers, size_t signerCount, + const uint8_t* payload, size_t payloadLen, + const uint8_t* detachedPayload, size_t detachedPayloadLen, + const uint8_t* extAad, size_t extAadLen, + uint8_t* scratch, size_t scratchSz, + uint8_t* out, size_t outSz, size_t* outLen, + WC_RNG* rng +); +``` + +Create a COSE_Sign message with multiple signers. + +**Parameters:** +| Name | Description | +|------|-------------| +| `signers` | Array of `WOLFCOSE_SIGNATURE` structures | +| `signerCount` | Number of signers | +| Other parameters | Same as `wc_CoseSign1_Sign` | + +--- + +### wc_CoseSign_Verify + +```c +int wc_CoseSign_Verify( + const WOLFCOSE_KEY* key, + size_t signerIdx, + const uint8_t* coseMsg, size_t coseMsgLen, + const uint8_t* detachedPayload, size_t detachedPayloadLen, + const uint8_t* extAad, size_t extAadLen, + uint8_t* scratch, size_t scratchSz, + WOLFCOSE_HDR* hdr, + const uint8_t** payload, size_t* payloadLen +); +``` + +Verify one signer's signature in a COSE_Sign message. + +**Parameters:** +| Name | Description | +|------|-------------| +| `key` | Verification key for the specific signer | +| `signerIdx` | Zero-based index of signer to verify | +| Other parameters | Same as `wc_CoseSign1_Verify` | + +--- + +## COSE_Encrypt API (Multi-Recipient) + +### wc_CoseEncrypt_Encrypt + +```c +int wc_CoseEncrypt_Encrypt( + const WOLFCOSE_RECIPIENT* recipients, size_t recipientCount, + int32_t contentAlgId, + const uint8_t* iv, size_t ivLen, + const uint8_t* payload, size_t payloadLen, + const uint8_t* detachedPayload, size_t detachedLen, + const uint8_t* extAad, size_t extAadLen, + uint8_t* scratch, size_t scratchSz, + uint8_t* out, size_t outSz, size_t* outLen, + WC_RNG* rng +); +``` + +Create a COSE_Encrypt message for multiple recipients. + +**Parameters:** +| Name | Description | +|------|-------------| +| `recipients` | Array of `WOLFCOSE_RECIPIENT` structures with keys and algorithms | +| `recipientCount` | Number of recipients | +| `contentAlgId` | Content encryption algorithm (e.g., `WOLFCOSE_ALG_A128GCM`) | +| `iv`, `ivLen` | Initialization vector (12 bytes for AES-GCM) | +| `payload`, `payloadLen` | Plaintext to encrypt (inline) | +| `detachedPayload`, `detachedLen` | Plaintext to encrypt but not include in message | +| `extAad`, `extAadLen` | External AAD | +| `scratch`, `scratchSz` | Scratch buffer | +| `out`, `outSz`, `outLen` | Output buffer | +| `rng` | Random number generator | + +**Returns:** `WOLFCOSE_SUCCESS` or error code + +--- + +### wc_CoseEncrypt_Decrypt + +```c +int wc_CoseEncrypt_Decrypt( + const WOLFCOSE_RECIPIENT* recipient, + size_t recipientIndex, + const uint8_t* in, size_t inSz, + const uint8_t* detachedCt, size_t detachedCtLen, + const uint8_t* extAad, size_t extAadLen, + uint8_t* scratch, size_t scratchSz, + WOLFCOSE_HDR* hdr, + uint8_t* plaintext, size_t plaintextSz, size_t* plaintextLen +); +``` + +Decrypt a COSE_Encrypt message as a specific recipient. + +**Parameters:** +| Name | Description | +|------|-------------| +| `recipient` | Recipient structure with key and algorithm | +| `recipientIndex` | Zero-based index of recipient in message | +| `in`, `inSz` | COSE_Encrypt message | +| `detachedCt`, `detachedCtLen` | Detached ciphertext (if applicable) | +| `extAad`, `extAadLen` | External AAD (must match encryption) | +| `scratch`, `scratchSz` | Scratch buffer | +| `hdr` | Receives parsed header | +| `plaintext`, `plaintextSz`, `plaintextLen` | Output buffer | + +**Returns:** `WOLFCOSE_SUCCESS`, `WOLFCOSE_E_COSE_DECRYPT_FAIL`, or other error + +--- + +## COSE_Mac API (Multi-Recipient) + +### wc_CoseMac_Create + +```c +int wc_CoseMac_Create( + const WOLFCOSE_RECIPIENT* recipients, size_t recipientCount, + int32_t macAlgId, + const uint8_t* payload, size_t payloadLen, + const uint8_t* detachedPayload, size_t detachedLen, + const uint8_t* extAad, size_t extAadLen, + uint8_t* scratch, size_t scratchSz, + uint8_t* out, size_t outSz, size_t* outLen +); +``` + +Create a COSE_Mac message for multiple recipients. + +**Parameters:** +| Name | Description | +|------|-------------| +| `recipients` | Array of `WOLFCOSE_RECIPIENT` structures | +| `recipientCount` | Number of recipients | +| `macAlgId` | MAC algorithm (e.g., `WOLFCOSE_ALG_HMAC_256_256`) | +| `payload`, `payloadLen` | Payload to include in message | +| `detachedPayload`, `detachedLen` | Payload to MAC but not include | +| `extAad`, `extAadLen` | External AAD | +| `scratch`, `scratchSz` | Scratch buffer | +| `out`, `outSz`, `outLen` | Output buffer | + +**Returns:** `WOLFCOSE_SUCCESS` or error code + +--- + +### wc_CoseMac_Verify + +```c +int wc_CoseMac_Verify( + const WOLFCOSE_RECIPIENT* recipient, + size_t recipientIndex, + const uint8_t* in, size_t inSz, + const uint8_t* detachedPayload, size_t detachedLen, + const uint8_t* extAad, size_t extAadLen, + uint8_t* scratch, size_t scratchSz, + WOLFCOSE_HDR* hdr, + const uint8_t** payload, size_t* payloadLen +); +``` + +Verify a COSE_Mac message as a specific recipient. + +**Parameters:** +| Name | Description | +|------|-------------| +| `recipient` | Recipient structure with key and algorithm | +| `recipientIndex` | Zero-based index of recipient in message | +| `in`, `inSz` | COSE_Mac message | +| `detachedPayload`, `detachedLen` | Detached payload (if applicable) | +| `extAad`, `extAadLen` | External AAD | +| `scratch`, `scratchSz` | Scratch buffer | +| `hdr` | Receives parsed header | +| `payload`, `payloadLen` | Receives payload pointer | + +**Returns:** `WOLFCOSE_SUCCESS`, `WOLFCOSE_E_MAC_FAIL`, or other error + +--- + +## CBOR API + +Basic CBOR encoding/decoding functions in `wolfcose.h`: + +### Encoding Functions + +| Function | Description | +|----------|-------------| +| `wc_CBOR_EncodeUint(ctx, val)` | Encode unsigned integer | +| `wc_CBOR_EncodeInt(ctx, val)` | Encode signed integer | +| `wc_CBOR_EncodeBstr(ctx, data, len)` | Encode byte string | +| `wc_CBOR_EncodeTstr(ctx, str, len)` | Encode text string | +| `wc_CBOR_EncodeArrayStart(ctx, count)` | Encode array header | +| `wc_CBOR_EncodeMapStart(ctx, count)` | Encode map header | +| `wc_CBOR_EncodeTag(ctx, tag)` | Encode CBOR tag | +| `wc_CBOR_EncodeNull(ctx)` | Encode null | +| `wc_CBOR_EncodeTrue(ctx)` / `wc_CBOR_EncodeFalse(ctx)` | Encode booleans | + +### Decoding Functions + +| Function | Description | +|----------|-------------| +| `wc_CBOR_DecodeUint(ctx, val)` | Decode unsigned integer | +| `wc_CBOR_DecodeInt(ctx, val)` | Decode signed integer | +| `wc_CBOR_DecodeBstr(ctx, data, len)` | Decode byte string (zero-copy) | +| `wc_CBOR_DecodeTstr(ctx, str, len)` | Decode text string (zero-copy) | +| `wc_CBOR_DecodeArrayStart(ctx, count)` | Decode array header | +| `wc_CBOR_DecodeMapStart(ctx, count)` | Decode map header | +| `wc_CBOR_DecodeTag(ctx, tag)` | Decode CBOR tag | +| `wc_CBOR_Skip(ctx)` | Skip over any CBOR item | +| `wc_CBOR_PeekType(ctx)` | Peek at next item's major type | + +--- + +## Error Codes + +| Code | Name | Description | +|------|------|-------------| +| 0 | `WOLFCOSE_SUCCESS` | Operation completed successfully | +| -9000 | `WOLFCOSE_E_INVALID_ARG` | Invalid argument (NULL pointer, etc.) | +| -9001 | `WOLFCOSE_E_BUFFER_TOO_SMALL` | Output buffer insufficient | +| -9002 | `WOLFCOSE_E_CBOR_MALFORMED` | CBOR parsing error | +| -9003 | `WOLFCOSE_E_CBOR_TYPE` | Unexpected CBOR type | +| -9004 | `WOLFCOSE_E_CBOR_OVERFLOW` | Integer overflow in CBOR | +| -9006 | `WOLFCOSE_E_CBOR_DEPTH` | CBOR nesting too deep | +| -9010 | `WOLFCOSE_E_COSE_BAD_TAG` | Wrong COSE tag for message type | +| -9011 | `WOLFCOSE_E_COSE_BAD_ALG` | Unsupported or invalid algorithm | +| -9012 | `WOLFCOSE_E_COSE_SIG_FAIL` | Signature verification failed | +| -9013 | `WOLFCOSE_E_COSE_DECRYPT_FAIL` | Decryption/authentication failed | +| -9014 | `WOLFCOSE_E_COSE_BAD_HDR` | Invalid COSE header | +| -9015 | `WOLFCOSE_E_COSE_KEY_TYPE` | Wrong key type for operation | +| -9016 | `WOLFCOSE_E_COSE_MAC_FAIL` | COSE MAC verification failed | +| -9020 | `WOLFCOSE_E_CRYPTO` | wolfCrypt error | +| -9021 | `WOLFCOSE_E_UNSUPPORTED` | Feature not supported | +| -9022 | `WOLFCOSE_E_MAC_FAIL` | MAC verification failed | +| -9023 | `WOLFCOSE_E_DETACHED_PAYLOAD` | Detached payload required but not provided | + +--- + +## See Also + +- [[Getting Started]]: Build instructions and examples +- [[Algorithms]]: Supported algorithms +- [[Macros]]: Compile-time configuration diff --git a/docs/Algorithms.md b/docs/Algorithms.md new file mode 100644 index 0000000..5512616 --- /dev/null +++ b/docs/Algorithms.md @@ -0,0 +1,181 @@ +# Supported Algorithms + +wolfCOSE supports 40 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. + +## COSE_Sign1 (Digital Signatures) + +| Algorithm | COSE ID | wolfCrypt Guard | Notes | +|-----------|---------|-----------------|-------| +| ES256 | -7 | `HAVE_ECC` | ECDSA with P-256 / SHA-256 | +| ES384 | -35 | `HAVE_ECC` | ECDSA with P-384 / SHA-384 | +| ES512 | -36 | `HAVE_ECC` | ECDSA with P-521 / SHA-512 | +| EdDSA (Ed25519) | -8 | `HAVE_ED25519` | Curve25519 | +| EdDSA (Ed448) | -8 | `HAVE_ED448` | Curve448 (Goldilocks) | +| PS256 | -37 | `WC_RSA_PSS` | RSA-PSS with SHA-256 | +| PS384 | -38 | `WC_RSA_PSS` | RSA-PSS with SHA-384 | +| PS512 | -39 | `WC_RSA_PSS` | RSA-PSS with SHA-512 | +| ML-DSA-44 | -48 | `WOLFSSL_HAVE_MLDSA` | Post-quantum (FIPS 204) | +| ML-DSA-65 | -49 | `WOLFSSL_HAVE_MLDSA` | Post-quantum (FIPS 204) | +| ML-DSA-87 | -50 | `WOLFSSL_HAVE_MLDSA` | Post-quantum (FIPS 204) | + +### ML-DSA Signature Sizes + +| Algorithm | Signature Size | Public Key Size | +|-----------|----------------|-----------------| +| ML-DSA-44 | 2,420 bytes | 1,312 bytes | +| ML-DSA-65 | 3,293 bytes | 1,952 bytes | +| ML-DSA-87 | 4,595 bytes | 2,592 bytes | + +## COSE_Encrypt0 (Authenticated Encryption) + +| Algorithm | COSE ID | wolfCrypt Guard | Notes | +|-----------|---------|-----------------|-------| +| A128GCM | 1 | `HAVE_AESGCM` | AES-GCM 128-bit | +| A192GCM | 2 | `HAVE_AESGCM` | AES-GCM 192-bit | +| A256GCM | 3 | `HAVE_AESGCM` | AES-GCM 256-bit | +| ChaCha20/Poly1305 | 24 | `HAVE_CHACHA && HAVE_POLY1305` | 256-bit, software-friendly | +| AES-CCM-16-64-128 | 10 | `HAVE_AESCCM` | 128-bit key, 8-byte tag | +| AES-CCM-16-64-256 | 11 | `HAVE_AESCCM` | 256-bit key, 8-byte tag | +| AES-CCM-64-64-128 | 12 | `HAVE_AESCCM` | 128-bit key, 8-byte tag, short nonce | +| AES-CCM-64-64-256 | 13 | `HAVE_AESCCM` | 256-bit key, 8-byte tag, short nonce | +| AES-CCM-16-128-128 | 30 | `HAVE_AESCCM` | 128-bit key, 16-byte tag | +| AES-CCM-16-128-256 | 31 | `HAVE_AESCCM` | 256-bit key, 16-byte tag | +| AES-CCM-64-128-128 | 32 | `HAVE_AESCCM` | 128-bit key, 16-byte tag, short nonce | +| AES-CCM-64-128-256 | 33 | `HAVE_AESCCM` | 256-bit key, 16-byte tag, short nonce | + +### AES-CCM Naming Convention + +The AES-CCM algorithm names follow the pattern `AES-CCM-{L}-{T}-{K}`: +- **L**: Length field size (16 or 64 bits for nonce) +- **T**: Tag size (64 or 128 bits) +- **K**: Key size (128 or 256 bits) + +## COSE_Mac0 (Message Authentication) + +| Algorithm | COSE ID | wolfCrypt Guard | Notes | +|-----------|---------|-----------------|-------| +| HMAC 256/256 | 5 | `!NO_HMAC` | SHA-256, 32-byte tag | +| HMAC 384/384 | 6 | `WOLFSSL_SHA384` | SHA-384, 48-byte tag | +| HMAC 512/512 | 7 | `WOLFSSL_SHA512` | SHA-512, 64-byte tag | +| AES-MAC-128/64 | 14 | `HAVE_AES_CBC` | 128-bit key, 8-byte tag | +| AES-MAC-256/64 | 15 | `HAVE_AES_CBC` | 256-bit key, 8-byte tag | +| AES-MAC-128/128 | 25 | `HAVE_AES_CBC` | 128-bit key, 16-byte tag | +| AES-MAC-256/128 | 26 | `HAVE_AES_CBC` | 256-bit key, 16-byte tag | + +## Key Distribution (Multi-Recipient) + +Used with COSE_Encrypt and COSE_Mac for multi-recipient messages: + +| Algorithm | COSE ID | wolfCrypt Guard | Notes | +|-----------|---------|-----------------|-------| +| Direct | -6 | always | Pre-shared symmetric key | +| A128KW | -3 | `HAVE_AES_KEYWRAP` | AES Key Wrap 128-bit | +| A192KW | -4 | `HAVE_AES_KEYWRAP` | AES Key Wrap 192-bit | +| A256KW | -5 | `HAVE_AES_KEYWRAP` | AES Key Wrap 256-bit | +| ECDH-ES+HKDF-256 | -25 | `HAVE_ECC && HAVE_HKDF` | Ephemeral-Static ECDH | +| ECDH-ES+HKDF-512 | -26 | `HAVE_ECC && HAVE_HKDF` | Ephemeral-Static ECDH | +| ECDH-SS+HKDF-256 | -27 | `HAVE_ECC && HAVE_HKDF` | Static-Static ECDH | +| ECDH-SS+HKDF-512 | -28 | `HAVE_ECC && HAVE_HKDF` | Static-Static ECDH | +| ECDH-ES+A128KW | -29 | `HAVE_ECC && HAVE_HKDF && HAVE_AES_KEYWRAP` | ECDH + Key Wrap | +| ECDH-ES+A192KW | -30 | `HAVE_ECC && HAVE_HKDF && HAVE_AES_KEYWRAP` | ECDH + Key Wrap | +| ECDH-ES+A256KW | -31 | `HAVE_ECC && HAVE_HKDF && HAVE_AES_KEYWRAP` | ECDH + Key Wrap | + +## Key Types + +| COSE kty | Value | Guard | Algorithms | +|----------|-------|-------|------------| +| OKP | 1 | `HAVE_ED25519` / `HAVE_ED448` / `WOLFSSL_HAVE_MLDSA` | EdDSA, ML-DSA | +| EC2 | 2 | `HAVE_ECC` | ES256, ES384, ES512 | +| RSA | 3 | `WC_RSA_PSS` | PS256, PS384, PS512 | +| Symmetric | 4 | always | AES-GCM, AES-CCM, ChaCha20, HMAC | + +## Curves + +| COSE crv | Value | Description | +|----------|-------|-------------| +| P-256 | 1 | NIST P-256 (secp256r1) | +| P-384 | 2 | NIST P-384 (secp384r1) | +| P-521 | 3 | NIST P-521 (secp521r1) | +| Ed25519 | 6 | Ed25519 for signatures | +| Ed448 | 7 | Ed448 for signatures | + +## COSE Tags + +| Tag | Value | Message Type | +|-----|-------|--------------| +| COSE_Encrypt0 | 16 | Symmetric encryption (single key) | +| COSE_Mac0 | 17 | Symmetric MAC (single key) | +| COSE_Sign1 | 18 | Single signer signature | +| COSE_Encrypt | 96 | Multi-recipient encryption | +| COSE_Mac | 97 | Multi-recipient MAC | +| COSE_Sign | 98 | Multi-signer signature | + +## Algorithm Constants in Code + +wolfCOSE defines these constants in `wolfcose.h`: + +```c +/* Signature algorithms */ +#define WOLFCOSE_ALG_ES256 (-7) +#define WOLFCOSE_ALG_ES384 (-35) +#define WOLFCOSE_ALG_ES512 (-36) +#define WOLFCOSE_ALG_EDDSA (-8) +#define WOLFCOSE_ALG_PS256 (-37) +#define WOLFCOSE_ALG_PS384 (-38) +#define WOLFCOSE_ALG_PS512 (-39) +#define WOLFCOSE_ALG_ML_DSA_44 (-48) +#define WOLFCOSE_ALG_ML_DSA_65 (-49) +#define WOLFCOSE_ALG_ML_DSA_87 (-50) + +/* Encryption algorithms */ +#define WOLFCOSE_ALG_A128GCM (1) +#define WOLFCOSE_ALG_A192GCM (2) +#define WOLFCOSE_ALG_A256GCM (3) +#define WOLFCOSE_ALG_CHACHA20_POLY1305 (24) +#define WOLFCOSE_ALG_AES_CCM_16_64_128 (10) +#define WOLFCOSE_ALG_AES_CCM_16_64_256 (11) +/* ... and more */ + +/* MAC algorithms */ +#define WOLFCOSE_ALG_HMAC_256_256 (5) +#define WOLFCOSE_ALG_HMAC_384_384 (6) +#define WOLFCOSE_ALG_HMAC_512_512 (7) +#define WOLFCOSE_ALG_AES_MAC_128_64 (14) +/* ... and more */ + +/* Key distribution */ +#define WOLFCOSE_ALG_DIRECT (-6) +#define WOLFCOSE_ALG_A128KW (-3) +#define WOLFCOSE_ALG_A192KW (-4) +#define WOLFCOSE_ALG_A256KW (-5) +#define WOLFCOSE_ALG_ECDH_ES_HKDF_256 (-25) +#define WOLFCOSE_ALG_ECDH_ES_HKDF_512 (-26) + +/* Key types */ +#define WOLFCOSE_KTY_OKP (1) +#define WOLFCOSE_KTY_EC2 (2) +#define WOLFCOSE_KTY_SYMMETRIC (4) + +/* Curves */ +#define WOLFCOSE_CRV_P256 (1) +#define WOLFCOSE_CRV_P384 (2) +#define WOLFCOSE_CRV_P521 (3) +#define WOLFCOSE_CRV_ED25519 (6) +#define WOLFCOSE_CRV_ED448 (7) +``` + +## Roadmap + +Future algorithm support planned: + +| Algorithm | Standard | Description | +|-----------|----------|-------------| +| ML-KEM | FIPS 203 (Kyber) | Post-quantum key encapsulation for COSE_Encrypt | +| XMSS / LMS | NIST SP 800-208 | Hash-based stateful signatures | +| SLH-DSA | SPHINCS+ | Stateless hash-based signatures | + +## See Also + +- [[Getting Started]]: Build instructions and examples +- [[API Reference]]: Function documentation +- [[Macros]]: Compile-time configuration diff --git a/docs/Getting-Started.md b/docs/Getting-Started.md new file mode 100644 index 0000000..66a1a79 --- /dev/null +++ b/docs/Getting-Started.md @@ -0,0 +1,360 @@ +# Getting Started + +This guide covers prerequisites, building wolfCOSE, and basic usage examples. + +## Prerequisites + +### wolfSSL Installation + +wolfCOSE requires wolfSSL 5.x with the appropriate algorithms enabled. Here's a full-featured build: + +```bash +cd wolfssl +./autogen.sh +./configure --enable-ecc --enable-ed25519 --enable-ed448 \ + --enable-curve25519 --enable-aesgcm --enable-aesccm \ + --enable-sha384 --enable-sha512 --enable-keygen \ + --enable-rsapss --enable-chacha --enable-poly1305 \ + --enable-mldsa --enable-hkdf --enable-aeskeywrap +make && sudo make install +sudo ldconfig +``` + +### Minimal Builds + +You can enable only the algorithms you need: + +**ECC + AES-GCM only:** +```bash +./configure --enable-ecc --enable-aesgcm --enable-sha384 \ + --enable-sha512 --enable-keygen +``` + +**Post-quantum only (ML-DSA):** +```bash +./configure --enable-mldsa --enable-sha512 +``` + +**ECDH-ES + Key Wrap (multi-recipient encryption):** +```bash +./configure --enable-ecc --enable-aesgcm --enable-sha384 \ + --enable-sha512 --enable-keygen --enable-hkdf --enable-aeskeywrap +``` + +### Feature to wolfSSL Flag Mapping + +| Feature | wolfSSL Configure Flags | +|---------|------------------------| +| ECC signing (ES256/384/512) | `--enable-ecc --enable-keygen` | +| EdDSA (Ed25519) | `--enable-ed25519 --enable-curve25519` | +| EdDSA (Ed448) | `--enable-ed448` | +| AES-GCM encryption | `--enable-aesgcm` | +| AES-CCM encryption | `--enable-aesccm` | +| ChaCha20-Poly1305 | `--enable-chacha --enable-poly1305` | +| ECDH-ES key agreement | `--enable-ecc --enable-hkdf` | +| AES Key Wrap | `--enable-aeskeywrap` | +| RSA-PSS signing | `--enable-rsapss --enable-keygen` | +| ML-DSA (post-quantum) | `--enable-mldsa` | +| AES-MAC | `--enable-aescbc` | + +## Building wolfCOSE + +```bash +git clone https://github.com/wolfSSL/wolfCOSE.git +cd wolfCOSE +make +``` + +### Build Targets + +| Target | Description | +|--------|-------------| +| `make all` | Build `libwolfcose.a` (static library) | +| `make shared` | Build `libwolfcose.so` (shared library) | +| `make test` | Build and run CBOR and COSE unit tests | +| `make tool` | Build CLI tool (`tools/wolfcose_tool`) | +| `make tool-test` | Round-trip self-test for all 17 algorithms | +| `make demo` | Build and run lifecycle demo (11 algorithms) | +| `make demos` | Build and run all basic demos | +| `make comprehensive` | Build and run comprehensive algorithm tests (~240 tests) | +| `make scenarios` | Build and run real-world scenario examples | +| `make coverage` | Run tests with gcov coverage | +| `make clean` | Remove all build artifacts | + +## Quick Start: Sign and Verify + +```c +#include +#include + +int main(void) +{ + ecc_key eccKey; + WOLFCOSE_KEY coseKey; + uint8_t scratch[WOLFCOSE_MAX_SCRATCH_SZ]; + uint8_t out[256]; + size_t outLen; + WC_RNG rng; + + const uint8_t payload[] = "Hello, COSE!"; + const uint8_t kid[] = "key-1"; + + /* Initialize RNG */ + wc_InitRng(&rng); + + /* Generate ECC key */ + wc_ecc_init(&eccKey); + wc_ecc_make_key(&rng, 32, &eccKey); + + /* Wrap in COSE key structure */ + wc_CoseKey_Init(&coseKey); + wc_CoseKey_SetEcc(&coseKey, WOLFCOSE_CRV_P256, &eccKey); + + /* Sign */ + wc_CoseSign1_Sign(&coseKey, WOLFCOSE_ALG_ES256, + kid, sizeof(kid) - 1, + payload, sizeof(payload) - 1, + NULL, 0, /* no detached payload */ + NULL, 0, /* no external AAD */ + scratch, sizeof(scratch), + out, sizeof(out), &outLen, + &rng); + + /* Verify */ + WOLFCOSE_HDR hdr; + const uint8_t* decoded; + size_t decodedLen; + + int ret = wc_CoseSign1_Verify(&coseKey, + out, outLen, + NULL, 0, /* no detached payload */ + NULL, 0, /* no external AAD */ + scratch, sizeof(scratch), + &hdr, &decoded, &decodedLen); + + if (ret == WOLFCOSE_SUCCESS) { + printf("Verified! Payload: %.*s\n", (int)decodedLen, decoded); + } + + /* Cleanup */ + wc_ecc_free(&eccKey); + wc_FreeRng(&rng); + + return 0; +} +``` + +## Quick Start: Encrypt and Decrypt + +```c +#include +#include + +int main(void) +{ + WOLFCOSE_KEY coseKey; + uint8_t scratch[WOLFCOSE_MAX_SCRATCH_SZ]; + uint8_t out[256]; + uint8_t plaintext[256]; + size_t outLen, plaintextLen; + + /* 128-bit symmetric key */ + uint8_t symKey[16] = { + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f + }; + + /* 12-byte IV for AES-GCM */ + uint8_t iv[12] = { + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, + 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b + }; + + const uint8_t data[] = "Secret message"; + + /* Setup symmetric key */ + wc_CoseKey_Init(&coseKey); + wc_CoseKey_SetSymmetric(&coseKey, symKey, sizeof(symKey)); + + /* Encrypt */ + wc_CoseEncrypt0_Encrypt(&coseKey, WOLFCOSE_ALG_A128GCM, + iv, sizeof(iv), + data, sizeof(data) - 1, + NULL, 0, NULL, /* no detached ciphertext */ + NULL, 0, /* no external AAD */ + scratch, sizeof(scratch), + out, sizeof(out), &outLen); + + /* Decrypt */ + WOLFCOSE_HDR hdr; + + int ret = wc_CoseEncrypt0_Decrypt(&coseKey, + out, outLen, + NULL, 0, /* no detached ciphertext */ + NULL, 0, /* no external AAD */ + scratch, sizeof(scratch), + &hdr, + plaintext, sizeof(plaintext), &plaintextLen); + + if (ret == WOLFCOSE_SUCCESS) { + printf("Decrypted: %.*s\n", (int)plaintextLen, plaintext); + } + + return 0; +} +``` + +## Quick Start: Post-Quantum Signing (ML-DSA) + +```c +#include +#include + +int main(void) +{ + wc_MlDsaKey mlDsaKey; + WOLFCOSE_KEY coseKey; + uint8_t scratch[8192]; /* PQC needs larger scratch */ + uint8_t out[8192]; + size_t outLen; + WC_RNG rng; + + const uint8_t payload[] = "Quantum-safe message"; + + wc_InitRng(&rng); + + /* Generate ML-DSA-44 key (Level 2) */ + wc_MlDsaKey_Init(&mlDsaKey, NULL, INVALID_DEVID); + wc_MlDsaKey_SetParams(&mlDsaKey, WC_ML_DSA_44); + wc_MlDsaKey_MakeKey(&mlDsaKey, &rng); + + /* Wrap in COSE key */ + wc_CoseKey_Init(&coseKey); + wc_CoseKey_SetMlDsa(&coseKey, WOLFCOSE_ALG_ML_DSA_44, &mlDsaKey); + + /* Sign */ + wc_CoseSign1_Sign(&coseKey, WOLFCOSE_ALG_ML_DSA_44, + NULL, 0, + payload, sizeof(payload) - 1, + NULL, 0, NULL, 0, + scratch, sizeof(scratch), + out, sizeof(out), &outLen, + &rng); + + /* Verify */ + WOLFCOSE_HDR hdr; + const uint8_t* decoded; + size_t decodedLen; + + wc_CoseSign1_Verify(&coseKey, + out, outLen, + NULL, 0, NULL, 0, + scratch, sizeof(scratch), + &hdr, &decoded, &decodedLen); + + wc_MlDsaKey_Free(&mlDsaKey); + wc_FreeRng(&rng); + + return 0; +} +``` + +## CLI Tool + +The `wolfcose_tool` provides command-line access to all wolfCOSE operations: + +```bash +# Build the tool +make tool + +# Generate keys +./tools/wolfcose_tool keygen -a ES256 -o ec.key +./tools/wolfcose_tool keygen -a ML-DSA-44 -o pqc.key +./tools/wolfcose_tool keygen -a A128GCM -o sym.key + +# Sign and verify +./tools/wolfcose_tool sign -k ec.key -a ES256 -i data.bin -o data.cose +./tools/wolfcose_tool verify -k ec.key -i data.cose + +# Encrypt and decrypt +./tools/wolfcose_tool enc -k sym.key -a A128GCM -i secret.bin -o secret.cose +./tools/wolfcose_tool dec -k sym.key -i secret.cose -o recovered.bin + +# MAC operations +./tools/wolfcose_tool keygen -a HMAC256 -o hmac.key +./tools/wolfcose_tool mac -k hmac.key -a HMAC256 -i data.bin -o data.mac +./tools/wolfcose_tool macverify -k hmac.key -i data.mac + +# Inspect COSE structure +./tools/wolfcose_tool info -i data.cose + +# Self-test all algorithms +./tools/wolfcose_tool test --all +``` + +## Examples Directory + +The `examples/` directory contains complete working examples: + +| File | Description | +|------|-------------| +| `sign1_demo.c` | All COSE_Sign1 algorithms | +| `encrypt0_demo.c` | All COSE_Encrypt0 algorithms | +| `mac0_demo.c` | All COSE_Mac0 algorithms | +| `lifecycle_demo.c` | Full edge-to-cloud workflow | + +### Comprehensive Tests (`examples/comprehensive/`) + +| File | Description | +|------|-------------| +| `sign_all.c` | Sign1 and multi-signer matrix tests (~61 tests) | +| `encrypt_all.c` | Encrypt0 and multi-recipient matrix tests (~23 tests) | +| `mac_all.c` | Mac0 and multi-recipient matrix tests (~32 tests) | +| `errors_all.c` | Error handling and edge cases (~19 tests) | + +### Real-World Scenarios (`examples/scenarios/`) + +| File | Description | +|------|-------------| +| `firmware_update.c` | Post-quantum ML-DSA firmware signing with detached payload | +| `multi_party_approval.c` | Dual-control firmware approval (ES256 + ES384) | +| `iot_fleet_config.c` | Encrypted config push to IoT device fleet | +| `sensor_attestation.c` | EAT-style attestation with replay protection via AAD | +| `group_broadcast_mac.c` | Authenticated broadcast to multiple subscribers | + +## Cross-Compilation + +For embedded targets: + +```bash +make CC=arm-none-eabi-gcc \ + CFLAGS="-std=c99 -Os -mcpu=cortex-m4 -mthumb \ + -I./include -I/path/to/wolfssl/include \ + -DWOLFSSL_USER_SETTINGS" +``` + +Provide a `user_settings.h` with your wolfSSL configuration instead of `wolfssl/options.h`. + +## Stack Budget + +Per-function stack usage (from `-fstack-usage`, GCC, `-Os`, aarch64): + +| Function | Stack (bytes) | +|----------|--------------| +| `wc_CoseSign1_Sign` | 464 | +| `wc_CoseSign1_Verify` | 288 | +| `wc_CoseEncrypt0_Encrypt` | 1120 | +| `wc_CoseEncrypt0_Decrypt` | 1072 | +| `wc_CoseMac0_Create` | 1104 | +| `wc_CoseMac0_Verify` | 1072 | +| `wc_CoseKey_Encode` | 352 | +| `wc_CoseKey_Decode` | 224 | +| `wc_CBOR_Skip` | 112 | +| CBOR encode/decode | 0-48 | + +## Next Steps + +- [[Algorithms]]: See all supported algorithms +- [[API Reference]]: Complete function documentation +- [[Macros]]: Configure compile-time options +- [[Testing]]: Run tests and measure coverage diff --git a/docs/Home.md b/docs/Home.md new file mode 100644 index 0000000..1cc3168 --- /dev/null +++ b/docs/Home.md @@ -0,0 +1,62 @@ +# 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 + +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 | +| Zero allocation | All operations use caller-provided buffers, no malloc | +| Tiny footprint | 7.5 KB minimal `.text` (Sign1+ECC), 25.6 KB full (40 algorithms), zero `.data`/`.bss` | +| 40 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 | +| [[Testing]] | Unit tests, coverage, and failure injection | +| [[Project Structure]] | Source code layout and file descriptions | + +## 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) + +## 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 new file mode 100644 index 0000000..7de1172 --- /dev/null +++ b/docs/MISRA-Compliance.md @@ -0,0 +1,127 @@ +# MISRA C Compliance + +wolfCOSE strives for MISRA C compliance and is checked in CI on every pull request. The project is not yet fully MISRA C:2023 compliant since there is no checker for 2023 that is publicly available yet. We do fully test and support the 2012 Misra-C standard. Full MISRA C:2023 verification requires commercial tooling (like LDRA, Polyspace, Cppcheck Premium). The current free tooling provides around 80% coverage across syntax, essential type, and data-flow rules. + +## Coverage + +### MISRA C:2012 + +Verified via cppcheck's MISRA addon (`--addon=misra`) with all wolfCOSE algorithm and feature macros defined. Covers ~65-75% of decidable MISRA C:2023 rules including: + +- Syntax rules (comments, declarations, expressions) +- Control flow rules (goto, switch, loops) +- Declaration and type rules +- Pointer and array rules + +**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. See [[Macros]] for the complete list. + +### MISRA C:2023 + +MISRA C:2023 is essentially MISRA C:2012 plus Amendments 1-4. Since free tooling does not directly support MISRA C:2023, compliance is approximated using two approaches: + +**Strict Compiler Warnings** 17 MISRA-adjacent GCC flags beyond the project's standard `-Wall -Wextra -Wpedantic -Wshadow -Wconversion`: + +| Flag | MISRA Rule | Purpose | +|------|-----------|---------| +| `-Wcast-qual` | Rule 11.8 | Const qualifier preservation | +| `-Wstrict-prototypes` | Rule 8.2 | Function declaration completeness | +| `-Wmissing-prototypes` | Rule 8.2 | Missing function prototypes | +| `-Wold-style-definition` | Rule 8.2 | Old-style function definitions | +| `-Wdeclaration-after-statement` | Rule 8.x | C90-style declaration ordering | +| `-Wundef` | Rule 20.9 | Undefined macro in `#if` | +| `-Wfloat-equal` | Rule 13.4 | Float equality comparison | +| `-Wpointer-arith` | Rule 18.x | Pointer arithmetic safety | +| `-Wredundant-decls` | Rule 8.x | Redundant declarations | +| `-Wnested-externs` | Rule 8.x | Nested extern declarations | +| `-Wformat=2` | Rule 21.6 | Format string safety | +| `-Wformat-security` | Rule 21.6 | Format string security | +| `-Wlogical-op` | Rule 12.x | Logical vs bitwise operators | +| `-Wjump-misses-init` | Rule 15.1 | Goto skipping initialization | +| `-Wdouble-promotion` | Rule 10.x | Implicit float-to-double | +| `-Wnull-dereference` | Safety | Null pointer dereference | +| `-Wsign-conversion` | Rule 10.x | Signed/unsigned conversion | + +**clang-tidy Checks** covers standard library safety (Amendment 3), deep data-flow analysis, and CERT C rules that map to MISRA 2023 logic: + +| Check Category | Coverage | +|---------------|----------| +| `bugprone-*` | Unsafe patterns (buffer overflows, integer overflows, suspicious constructs) | +| `cert-*` | CERT C rules mapping to MISRA 2023 logic | +| `clang-analyzer-*` | Inter-procedural data-flow analysis, pointer tracking | +| `misc-*` | Miscellaneous safety checks (excluding `misc-include-cleaner`) | + +**Workflow**: `.github/workflows/misra-2023.yml` + +## Coverage Summary + +| Area | cppcheck (2012) | Compiler Flags + clang-tidy (2023) | Commercial Tools | +|------|----------------|-----------------------------------|-----------------| +| Syntax Rules | High (~90%) | High (~95%) | 100% | +| Essential Types | Medium (~50%) | High (~80%) | 100% | +| Data Flow | Low (~30%) | Medium (~50%) | 100% | +| Std Lib Safety | Low (~20%) | Medium (~60%) | 100% | + +## Known Deviations in wolfCOSE + +wolfCOSE has the following documented MISRA C:2012 deviations. Each is suppressed in CI via `cppcheck --suppress` and justified below. + +### Rule 2.5: Unused Macro Definitions + +**Location:** `include/wolfcose/wolfcose.h` (feature gate macros) + +**Justification:** wolfCOSE feature-gate macros (`WOLFCOSE_SIGN1`, `WOLFCOSE_SIGN1_SIGN`, etc.) are defined conditionally via `#if !defined(NO_X) && !defined(X)` guards. When the CI passes both parent and child `-D` flags on the command line (e.g., `-DWOLFCOSE_SIGN1 -DWOLFCOSE_SIGN1_SIGN`), the child macro is pre-defined and the header guard skips the `#define`. cppcheck sees the guarded-away `#define` as "unused" — a false positive caused by the CI passing explicit flags for cppcheck path coverage. + +### Rule 8.7: Could Be Defined with Internal Linkage + +**Location:** `src/wolfcose.c:wolfCose_SigSize()` + +**Justification:** `wolfCose_SigSize()` is declared `WOLFCOSE_LOCAL` in `wolfcose_internal.h` and called from `tests/test_cose.c` for unit testing. cppcheck only scans `src/` and `include/`, so it does not see the test file usage and incorrectly reports the function could be `static`. Making it `static` would break the test suite. + +### Rule 11.8: Cast Removes Const Qualification + +**Location:** `src/wolfcose.c` (ECC/ECDH wolfSSL API calls) + +**Justification:** wolfSSL's ECC APIs (`wc_ecc_set_rng`, `wc_ecc_shared_secret`, `wc_ecc_sign_hash`, `wc_ecc_verify_hash`) take non-const `ecc_key*` parameters even for operations that do not modify the key data. wolfCOSE's public API correctly uses `const` qualifiers on key parameters (e.g., `const WOLFCOSE_KEY* key`) to communicate that keys are not modified. However, when passing the internal `ecc_key*` from a const `WOLFCOSE_KEY` to wolfSSL, cppcheck flags the implicit const-to-non-const conversion through the union member access chain. This is a wolfSSL API design limitation that wolfCOSE preserves const-correctness at its own API boundary but cannot enforce it through wolfSSL's non-const function signatures. + +### Rule 19.2: Union Type Used + +**Location:** `include/wolfcose/wolfcose.h:WOLFCOSE_KEY` struct (lines 443-464) + +**Justification:** The `WOLFCOSE_KEY` struct uses a tagged union to hold pointers to wolfCrypt key types (`ecc_key*`, `ed25519_key*`, `ed448_key*`, `RsaKey*`, `wc_MlDsaKey*`, symmetric key bytes). The `kty` field discriminates the active union member. This is the standard C pattern for polymorphic types and is fundamental to supporting a multi-algorithm COSE library without dynamic allocation. Replacing the union would require either: +- `void*` pointers (less type-safe, violates Rule 11.5) +- Separate functions per algorithm (massive API bloat) +- Dynamic allocation (violates the zero-allocation design constraint) + +### Rule 21.15: Overlapping Memory in Copy + +**Location:** `src/wolfcose.c:wolfCose_EccSignRaw()` (XMEMMOVE calls) + +**Justification:** `XMEMMOVE` (`memmove`) is used intentionally for overlapping memory regions when right-justifying ECC r/s signature components within a single buffer. The signature buffer contains `r||s` where `r` or `s` may be shorter than the coordinate size and needs to be shifted right with zero-padding. `memmove` is the correct function for this — it handles overlapping source and destination by design. cppcheck flags the overlap as a potential issue, but this is the intended behavior per RFC 8152 Section 8.1. + +## MISRA C:2023 Deviations (clang-tidy) + +The following clang-tidy checks are suppressed in the MISRA 2023 workflow. GCC strict MISRA warnings are fully clean (0 warnings). + +### bugprone-branch-clone: Identical Consecutive Switch Branches + +**Location:** `src/wolfcose.c` (algorithm dispatch switches) + +**Justification:** Different COSE algorithms intentionally map to the same wolfCrypt value. For example, ES512 and EdDSA both use `WC_HASH_TYPE_SHA512`, and A128GCM/A192GCM share the same nonce length. The switch branches are not bugs — they represent distinct algorithm IDs with identical cryptographic parameters. + +### bugprone-easily-swappable-parameters: Adjacent Parameters of Similar Types + +**Location:** Multiple public API functions + +**Justification:** Advisory warning about adjacent function parameters of the same type (e.g., `size_t payloadLen, size_t detachedLen`). Fixing requires reordering or wrapping parameters, which would break the public API. The parameter ordering follows RFC 9052 structure conventions. + +## Fully Compliant Rules (Notable) + +| Rule | Status | Notes | +|------|--------|-------| +| Rule 15.1 (no goto) | Compliant | All functions use cascading `if (ret == WOLFCOSE_SUCCESS)` with a single `return ret` | +| Rule 15.5 (single exit) | Compliant | All functions have exactly one return statement | +| Rule 17.2 (no recursion) | Compliant | CBOR decoder uses iterative traversal with a bounded stack (`WOLFCOSE_CBOR_MAX_DEPTH`) | +| Rule 17.7 (check returns) | Compliant | All return values checked or explicitly cast to `(void)` | +| Rule 12.1 (explicit precedence) | Compliant | All `&&`/`||` operands and mixed arithmetic explicitly parenthesized | diff --git a/docs/Macros.md b/docs/Macros.md new file mode 100644 index 0000000..b9f60b8 --- /dev/null +++ b/docs/Macros.md @@ -0,0 +1,232 @@ +# 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. + +## Message Type Gates + +### COSE_Sign1 (Single Signer) + +| Define | Description | Default | +|--------|-------------|---------| +| `WOLFCOSE_SIGN1` | Enable COSE_Sign1 message type | Enabled | +| `WOLFCOSE_NO_SIGN1` | Disable COSE_Sign1 entirely | - | +| `WOLFCOSE_SIGN1_SIGN` | Enable Sign1 creation | Enabled | +| `WOLFCOSE_NO_SIGN1_SIGN` | Disable Sign1 creation | - | +| `WOLFCOSE_SIGN1_VERIFY` | Enable Sign1 verification | Enabled | +| `WOLFCOSE_NO_SIGN1_VERIFY` | Disable Sign1 verification | - | + +### COSE_Encrypt0 (Symmetric Encryption) + +| Define | Description | Default | +|--------|-------------|---------| +| `WOLFCOSE_ENCRYPT0` | Enable COSE_Encrypt0 message type | Enabled | +| `WOLFCOSE_NO_ENCRYPT0` | Disable COSE_Encrypt0 entirely | - | +| `WOLFCOSE_ENCRYPT0_ENCRYPT` | Enable Encrypt0 creation | Enabled | +| `WOLFCOSE_NO_ENCRYPT0_ENCRYPT` | Disable Encrypt0 creation | - | +| `WOLFCOSE_ENCRYPT0_DECRYPT` | Enable Encrypt0 decryption | Enabled | +| `WOLFCOSE_NO_ENCRYPT0_DECRYPT` | Disable Encrypt0 decryption | - | + +### COSE_Mac0 (Symmetric MAC) + +| Define | Description | Default | +|--------|-------------|---------| +| `WOLFCOSE_MAC0` | Enable COSE_Mac0 message type | Enabled | +| `WOLFCOSE_NO_MAC0` | Disable COSE_Mac0 entirely | - | +| `WOLFCOSE_MAC0_CREATE` | Enable Mac0 creation | Enabled | +| `WOLFCOSE_NO_MAC0_CREATE` | Disable Mac0 creation | - | +| `WOLFCOSE_MAC0_VERIFY` | Enable Mac0 verification | Enabled | +| `WOLFCOSE_NO_MAC0_VERIFY` | Disable Mac0 verification | - | + +### COSE_Sign (Multi-Signer) + +| Define | Description | Default | +|--------|-------------|---------| +| `WOLFCOSE_SIGN` | Enable COSE_Sign (multi-signer) | Enabled | +| `WOLFCOSE_NO_SIGN` | Disable COSE_Sign entirely | - | +| `WOLFCOSE_SIGN_SIGN` | Enable Sign creation | Enabled | +| `WOLFCOSE_NO_SIGN_SIGN` | Disable Sign creation | - | +| `WOLFCOSE_SIGN_VERIFY` | Enable Sign verification | Enabled | +| `WOLFCOSE_NO_SIGN_VERIFY` | Disable Sign verification | - | + +### COSE_Encrypt (Multi-Recipient) + +| Define | Description | Default | +|--------|-------------|---------| +| `WOLFCOSE_ENCRYPT` | Enable COSE_Encrypt (multi-recipient) | Enabled | +| `WOLFCOSE_NO_ENCRYPT` | Disable COSE_Encrypt entirely | - | +| `WOLFCOSE_ENCRYPT_ENCRYPT` | Enable Encrypt creation | Enabled | +| `WOLFCOSE_NO_ENCRYPT_ENCRYPT` | Disable Encrypt creation | - | +| `WOLFCOSE_ENCRYPT_DECRYPT` | Enable Encrypt decryption | Enabled | +| `WOLFCOSE_NO_ENCRYPT_DECRYPT` | Disable Encrypt decryption | - | + +### COSE_Mac (Multi-Recipient) + +| Define | Description | Default | +|--------|-------------|---------| +| `WOLFCOSE_MAC` | Enable COSE_Mac (multi-recipient) | Enabled | +| `WOLFCOSE_NO_MAC` | Disable COSE_Mac entirely | - | +| `WOLFCOSE_MAC_CREATE` | Enable Mac creation | Enabled | +| `WOLFCOSE_NO_MAC_CREATE` | Disable Mac creation | - | +| `WOLFCOSE_MAC_VERIFY` | Enable Mac verification | Enabled | +| `WOLFCOSE_NO_MAC_VERIFY` | Disable Mac verification | - | + +--- + +## Key Distribution Gates + +| 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`) + +--- + +## CBOR Layer Gates + +| Define | Description | Default | +|--------|-------------|---------| +| `WOLFCOSE_CBOR_ENCODE` | Enable CBOR encoding | Enabled | +| `WOLFCOSE_NO_CBOR_ENCODE` | Disable CBOR encoding | - | +| `WOLFCOSE_CBOR_DECODE` | Enable CBOR decoding | Enabled | +| `WOLFCOSE_NO_CBOR_DECODE` | Disable CBOR decoding | - | + +--- + +## COSE_Key Gates + +| Define | Description | Default | +|--------|-------------|---------| +| `WOLFCOSE_KEY_ENCODE` | Enable COSE_Key encoding | Enabled | +| `WOLFCOSE_NO_KEY_ENCODE` | Disable COSE_Key encoding | - | +| `WOLFCOSE_KEY_DECODE` | Enable COSE_Key decoding | Enabled | +| `WOLFCOSE_NO_KEY_DECODE` | Disable COSE_Key decoding | - | + +--- + +## Size Configuration + +| Define | Description | Default | +|--------|-------------|---------| +| `WOLFCOSE_MAX_SCRATCH_SZ` | Scratch buffer size for Sig_structure/Enc_structure | 512 | +| `WOLFCOSE_PROTECTED_HDR_MAX` | Max protected header size | 64 | +| `WOLFCOSE_CBOR_MAX_DEPTH` | Max CBOR nesting depth | 8 | + +### Tuning for Constrained Targets + +```c +/* In your user_settings.h or build flags: */ + +/* Reduce scratch buffer (default 512, minimum depends on payload size) */ +#define WOLFCOSE_MAX_SCRATCH_SZ 256 + +/* Reduce protected header buffer */ +#define WOLFCOSE_PROTECTED_HDR_MAX 32 + +/* Reduce CBOR nesting depth (default 8) */ +#define WOLFCOSE_CBOR_MAX_DEPTH 4 + +/* For PQC (ML-DSA), increase scratch and signature buffers */ +/* #define WOLFCOSE_MAX_SCRATCH_SZ 8192 */ +/* #define WOLFCOSE_MAX_SIG_SZ 4627 */ +``` + +--- + +## Example Build Configurations + +### Sign-Only Build (Minimal) + +```bash +make CFLAGS="-DWOLFCOSE_NO_ENCRYPT0 -DWOLFCOSE_NO_MAC0 -DWOLFCOSE_NO_ENCRYPT -DWOLFCOSE_NO_MAC" +``` + +### Verify-Only Build + +```bash +make CFLAGS="-DWOLFCOSE_NO_SIGN1_SIGN -DWOLFCOSE_NO_ENCRYPT0_ENCRYPT -DWOLFCOSE_NO_MAC0_CREATE" +``` + +### Sign1-Only Build (Smallest) + +```bash +make CFLAGS="-DWOLFCOSE_NO_ENCRYPT0 -DWOLFCOSE_NO_MAC0 -DWOLFCOSE_NO_SIGN -DWOLFCOSE_NO_ENCRYPT -DWOLFCOSE_NO_MAC" +``` + +### No Multi-Recipient Support + +```bash +make CFLAGS="-DWOLFCOSE_NO_RECIPIENTS" +``` + +--- + +## wolfSSL Dependencies + +wolfCOSE requires these wolfSSL features for full functionality: + +| wolfSSL Define | wolfCOSE Feature | +|----------------|------------------| +| `HAVE_ECC` | ECDSA signing (ES256/ES384/ES512), ECDH key agreement | +| `HAVE_ED25519` | EdDSA signing (Ed25519) | +| `HAVE_ED448` | EdDSA signing (Ed448) | +| `WOLFSSL_HAVE_MLDSA` | ML-DSA post-quantum signing | +| `WC_RSA_PSS` | RSA-PSS signing (PS256/PS384/PS512) | +| `HAVE_AESGCM` | AES-GCM encryption | +| `HAVE_AESCCM` | AES-CCM encryption | +| `HAVE_CHACHA && HAVE_POLY1305` | ChaCha20-Poly1305 encryption | +| `HAVE_AES_CBC` | AES-CBC-MAC | +| `NO_HMAC` (NOT defined) | HMAC algorithms | +| `WOLFSSL_SHA384` | SHA-384 for ES384, HMAC-384 | +| `WOLFSSL_SHA512` | SHA-512 for ES512, HMAC-512 | +| `HAVE_AES_KEYWRAP` | AES Key Wrap distribution | +| `HAVE_HKDF` | ECDH-ES key derivation | + +--- + +## Test and Example Gates + +### Comprehensive Test Gates + +Each comprehensive test file can be disabled: + +| Define | Description | +|--------|-------------| +| `WOLFCOSE_NO_EXAMPLE_SIGN_ALL` | Disable sign_all.c | +| `WOLFCOSE_NO_EXAMPLE_ENCRYPT_ALL` | Disable encrypt_all.c | +| `WOLFCOSE_NO_EXAMPLE_MAC_ALL` | Disable mac_all.c | +| `WOLFCOSE_NO_EXAMPLE_ERRORS_ALL` | Disable errors_all.c | + +Sub-gates within tests: + +| Define | Description | +|--------|-------------| +| `WOLFCOSE_NO_SIGN_ALL_ES256` | Skip ES256 tests in sign_all | +| `WOLFCOSE_NO_SIGN_ALL_MULTI` | Skip multi-signer tests | +| `WOLFCOSE_NO_ENCRYPT_ALL_A128GCM` | Skip A128GCM tests | +| `WOLFCOSE_NO_MAC_ALL_HMAC256` | Skip HMAC-256 tests | + +### Scenario Example Gates + +| Define | Description | +|--------|-------------| +| `WOLFCOSE_NO_EXAMPLE_FIRMWARE_UPDATE` | Disable firmware_update.c | +| `WOLFCOSE_NO_EXAMPLE_MULTI_PARTY` | Disable multi_party_approval.c | +| `WOLFCOSE_NO_EXAMPLE_IOT_FLEET` | Disable iot_fleet_config.c | +| `WOLFCOSE_NO_EXAMPLE_SENSOR_ATTEST` | Disable sensor_attestation.c | +| `WOLFCOSE_NO_EXAMPLE_GROUP_BROADCAST` | Disable group_broadcast_mac.c | + +--- + +## See Also + +- [[Getting Started]]: Build instructions +- [[Algorithms]]: Supported algorithms with guards +- [[Testing]]: Test configuration diff --git a/docs/Message-Types.md b/docs/Message-Types.md new file mode 100644 index 0000000..a629dc1 --- /dev/null +++ b/docs/Message-Types.md @@ -0,0 +1,172 @@ +# COSE Message Types + +wolfCOSE implements the complete RFC 9052 message set — all six COSE structures, including the multi-actor variants (`COSE_Sign`, `COSE_Encrypt`, `COSE_Mac`) that most embedded C COSE libraries omit. + +| Message | RFC 9052 | Tag | API | +|---|---|---|---| +| `COSE_Sign1` | Sec. 4.2 | 18 | `wc_CoseSign1_Sign` / `wc_CoseSign1_Verify` | +| `COSE_Sign` | Sec. 4.1 | 98 | `wc_CoseSign_Sign` / `wc_CoseSign_Verify` | +| `COSE_Encrypt0` | Sec. 5.2 | 16 | `wc_CoseEncrypt0_Encrypt` / `wc_CoseEncrypt0_Decrypt` | +| `COSE_Encrypt` | Sec. 5.1 | 96 | `wc_CoseEncrypt_Encrypt` / `wc_CoseEncrypt_Decrypt` | +| `COSE_Mac0` | Sec. 6.2 | 17 | `wc_CoseMac0_Create` / `wc_CoseMac0_Verify` | +| `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. + +## COSE_Sign1 — single-signer signature (RFC 9052 Sec. 4.2) + +`COSE_Sign1` is the most common COSE message: one signer, one signature. + +```c +WOLFCOSE_KEY key; +uint8_t out[1024]; +size_t outLen; +WC_RNG rng; + +wc_InitRng(&rng); +wc_CoseKey_Init(&key); +wc_CoseKey_SetEcc(&key, WOLFCOSE_CRV_P256, &eccPriv); + +int ret = wc_CoseSign1_Sign(&key, WOLFCOSE_ALG_ES256, + payload, payloadLen, + NULL, 0, /* no detached payload */ + NULL, 0, /* no external AAD */ + scratch, sizeof(scratch), + out, sizeof(out), &outLen, + &rng); +``` + +## COSE_Sign — multi-signer signature (RFC 9052 Sec. 4.1) + +`COSE_Sign` carries N independent signatures over the same payload. Use it for dual-control approval, certificate chains where multiple parties attest, or hybrid classical/PQC signatures during migration. Each signer has its own algorithm and `kid`. + +```c +WOLFCOSE_SIGNATURE signers[2] = { + { .algId = WOLFCOSE_ALG_ES256, + .key = &vendorKey, + .kid = (const uint8_t*)"vendor-2026", .kidLen = 11 }, + { .algId = WOLFCOSE_ALG_ML_DSA_65, /* hybrid: classical + PQC */ + .key = &oemKey, + .kid = (const uint8_t*)"oem-pqc-1", .kidLen = 9 }, +}; + +ret = wc_CoseSign_Sign(signers, 2, + firmware, firmwareLen, + NULL, 0, /* attached payload */ + NULL, 0, /* no external AAD */ + scratch, sizeof(scratch), + out, sizeof(out), &outLen, + &rng); +``` + +Verifiers select which signature to check by index: + +```c +ret = wc_CoseSign_Verify(&vendorPubKey, /*signerIndex=*/0, + in, inLen, + NULL, 0, NULL, 0, + scratch, sizeof(scratch), + &hdr, &payload, &payloadLen); +``` + +## COSE_Encrypt0 — single-recipient AEAD (RFC 9052 Sec. 5.2) + +Direct symmetric AEAD. The caller already has the content encryption key (CEK). + +```c +ret = wc_CoseEncrypt0_Encrypt(&aesKey, WOLFCOSE_ALG_A128GCM, + iv, sizeof(iv), + plaintext, plaintextLen, + NULL, 0, NULL, 0, + scratch, sizeof(scratch), + out, sizeof(out), &outLen, + &rng); +``` + +## COSE_Encrypt — multi-recipient AEAD (RFC 9052 Sec. 5.1) + +`COSE_Encrypt` produces one ciphertext addressable by any of N recipients. Each recipient entry describes how that recipient learns the CEK: pre-shared (Direct), wrapped under a recipient KEK (`A128KW` / `A192KW` / `A256KW`), or derived via ECDH. + +```c +WOLFCOSE_RECIPIENT recipients[3] = { + { .algId = WOLFCOSE_ALG_DIRECT, + .key = &fleetSharedKey, + .kid = (const uint8_t*)"fleet-2026", .kidLen = 10 }, + { .algId = WOLFCOSE_ALG_A256KW, + .key = &device42Kek, + .kid = (const uint8_t*)"dev-42", .kidLen = 6 }, + { .algId = WOLFCOSE_ALG_ECDH_ES_HKDF_256, + .key = &device43Pub, + .kid = (const uint8_t*)"dev-43", .kidLen = 6 }, +}; + +ret = wc_CoseEncrypt_Encrypt(recipients, 3, + WOLFCOSE_ALG_A128GCM, /* content alg */ + iv, sizeof(iv), + config, configLen, + NULL, 0, NULL, 0, + scratch, sizeof(scratch), + out, sizeof(out), &outLen, + &rng); +``` + +A receiving device decrypts by selecting its own recipient index: + +```c +ret = wc_CoseEncrypt_Decrypt(&myRecipient, /*recipientIndex=*/1, + in, inLen, + NULL, 0, NULL, 0, + scratch, sizeof(scratch), + &hdr, plaintext, sizeof(plaintext), &plaintextLen); +``` + +## COSE_Mac0 — single-recipient MAC (RFC 9052 Sec. 6.2) + +Direct MAC over a payload using a pre-shared key. + +```c +ret = wc_CoseMac0_Create(&hmacKey, WOLFCOSE_ALG_HMAC_256_256, + payload, payloadLen, + NULL, 0, NULL, 0, + scratch, sizeof(scratch), + out, sizeof(out), &outLen); +``` + +## COSE_Mac — multi-recipient MAC (RFC 9052 Sec. 6.1) + +`COSE_Mac` carries one MAC tag plus per-recipient envelopes describing how each recipient learns the MAC key. Useful for group broadcast scenarios where every subscriber needs to authenticate the same payload but holds a different KEK. + +```c +WOLFCOSE_RECIPIENT subscribers[N] = { /* one entry per group member */ }; + +ret = wc_CoseMac_Create(subscribers, N, + WOLFCOSE_ALG_HMAC_256_256, + payload, payloadLen, + NULL, 0, NULL, 0, + scratch, sizeof(scratch), + out, sizeof(out), &outLen); +``` + +## Detached payloads + +Every `Sign*`, `Encrypt*`, and `Mac*` API accepts a detached payload — the COSE message stores only the signature/MAC/ciphertext and a `nil` payload field, while the actual bytes live elsewhere. This is essential when signing large objects (firmware, OTA images) where you don't want to copy the payload through the COSE buffer. Pass the payload via the `detachedPayload` / `detachedLen` arguments instead of `payload` / `payloadLen`, and the same on verify. + +## Compile-time stripping + +You only pay for the message types you use. Define the appropriate `WOLFCOSE_NO_*` macros to strip unused code paths: + +```c +-DWOLFCOSE_NO_SIGN -DWOLFCOSE_NO_ENCRYPT -DWOLFCOSE_NO_MAC /* multi-actor only */ +-DWOLFCOSE_NO_ENCRYPT0 -DWOLFCOSE_NO_MAC0 /* sign-only build */ +-DWOLFCOSE_NO_SIGN1_SIGN -DWOLFCOSE_NO_CBOR_ENCODE /* verify-only build */ +``` + +A minimal Sign1-verify-only build is around **7.5 KB of `.text`**, including the built-in CBOR engine. + +## 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 +- [`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/Project-Structure.md b/docs/Project-Structure.md new file mode 100644 index 0000000..4fcba5d --- /dev/null +++ b/docs/Project-Structure.md @@ -0,0 +1,249 @@ +# Project Structure + +This page describes the source code layout and file organization of wolfCOSE. + +## Directory Layout + +``` +wolfCOSE/ +├── include/ +│ └── wolfcose/ +│ ├── wolfcose.h # Public API (types, constants, all functions) +│ └── visibility.h # WOLFCOSE_API export macros +├── src/ +│ ├── wolfcose.c # COSE messages + key management +│ ├── wolfcose_cbor.c # CBOR encoder/decoder +│ └── wolfcose_internal.h # Internal helpers +├── tests/ +│ ├── test_cbor.c # CBOR unit tests +│ ├── test_cose.c # COSE unit tests +│ ├── test_interop.c # Interoperability tests +│ ├── test_main.c # Test harness +│ ├── force_failure.c # Failure injection +│ ├── force_failure.h # Failure injection API +│ └── vectors/ # Test vectors +├── tools/ +│ └── wolfcose_tool.c # CLI tool +├── examples/ +│ ├── sign1_demo.c # Sign1 algorithm demo +│ ├── encrypt0_demo.c # Encrypt0 algorithm demo +│ ├── mac0_demo.c # Mac0 algorithm demo +│ ├── lifecycle_demo.c # Edge-to-cloud demo +│ ├── comprehensive/ # Algorithm matrix tests +│ │ ├── sign_all.c +│ │ ├── encrypt_all.c +│ │ ├── mac_all.c +│ │ └── errors_all.c +│ └── scenarios/ # Real-world scenarios +│ ├── firmware_update.c +│ ├── multi_party_approval.c +│ ├── iot_fleet_config.c +│ ├── sensor_attestation.c +│ └── group_broadcast_mac.c +├── Makefile +└── README.md +``` + +--- + +## Core Library Files + +### include/wolfcose/wolfcose.h + +The public API header. Contains: +- All type definitions (`WOLFCOSE_KEY`, `WOLFCOSE_HDR`, etc.) +- Algorithm constants (`WOLFCOSE_ALG_ES256`, etc.) +- Key type and curve constants +- COSE tag values +- Error codes +- All function declarations + +### include/wolfcose/visibility.h + +Export macros for shared library builds: +- `WOLFCOSE_API` for public functions +- Platform-specific visibility attributes + +### src/wolfcose.c + +COSE message implementation (RFC 9052/9053). Contains: +- COSE_Sign1 / COSE_Sign functions +- COSE_Encrypt0 / COSE_Encrypt functions +- COSE_Mac0 / COSE_Mac functions +- COSE_Key encoding/decoding +- Sig_structure / Enc_structure / MAC_structure builders +- Crypto dispatch to wolfCrypt + +This file depends on wolfCrypt for all cryptographic operations. + +### src/wolfcose_cbor.c + +CBOR encoder/decoder (RFC 8949). Contains: +- Major type encoding/decoding +- Integer, byte string, text string handling +- Array and map handling +- Tag encoding/decoding +- Skip functionality for unknown items +- Zero-copy decoding (pointers into input buffer) + +This file has no wolfCrypt dependency. CBOR-only projects can link just `wolfcose_cbor.o`. + +### src/wolfcose_internal.h + +Internal helpers not exposed in public API: +- Big-endian macros for CBOR encoding +- Protected header codec +- AEAD algorithm dispatch tables +- Internal constants + +--- + +## Build Outputs + +| File | Description | +|------|-------------| +| `libwolfcose.a` | Static library | +| `libwolfcose.so` | Shared library (with `make shared`) | +| `tests/test_wolfcose` | Test executable | +| `tools/wolfcose_tool` | CLI tool executable | + +The core library is just two object files: +- `wolfcose.o` (COSE + Key) +- `wolfcose_cbor.o` (CBOR only) + +--- + +## Test Files + +### tests/test_cbor.c + +CBOR unit tests covering: +- RFC 8949 Appendix A encoding vectors +- Decoding tests for all major types +- Round-trip encode/decode tests +- Nested structure tests +- Skip functionality tests +- Error case handling + +### tests/test_cose.c + +COSE unit tests covering: +- All six message types (Sign1, Sign, Encrypt0, Encrypt, Mac0, Mac) +- All supported algorithms +- Detached payload mode +- External AAD +- Multi-signer and multi-recipient messages +- Error handling (tampered messages, wrong keys, etc.) + +### tests/test_interop.c + +Interoperability tests with: +- COSE Working Group test vectors +- RFC examples +- Cross-implementation compatibility + +### tests/test_main.c + +Test harness that: +- Initializes wolfCrypt +- Runs all test suites +- Reports pass/fail with CI-compatible exit codes + +### tests/force_failure.c / force_failure.h + +Failure injection system for coverage testing. See [[Testing]] for details. + +--- + +## CLI Tool + +### tools/wolfcose_tool.c + +Command-line interface providing: +- Key generation for all algorithm types +- Sign and verify operations +- Encrypt and decrypt operations +- MAC create and verify operations +- COSE message inspection (info command) +- Self-test functionality + +Supported commands: +``` +keygen - Generate a new key +sign - Create COSE_Sign1 message +verify - Verify COSE_Sign1 message +enc - Create COSE_Encrypt0 message +dec - Decrypt COSE_Encrypt0 message +mac - Create COSE_Mac0 message +macverify - Verify COSE_Mac0 message +info - Display COSE message structure +test - Run self-tests +``` + +--- + +## Examples + +### Basic Demos + +| File | Description | +|------|-------------| +| `sign1_demo.c` | Demonstrates all Sign1 algorithms (ES256, ES384, ES512, EdDSA, PS256/384/512, ML-DSA) | +| `encrypt0_demo.c` | Demonstrates all Encrypt0 algorithms (AES-GCM, ChaCha20, AES-CCM) | +| `mac0_demo.c` | Demonstrates all Mac0 algorithms (HMAC, AES-MAC) | +| `lifecycle_demo.c` | Full edge-to-cloud workflow with 11 algorithms | + +### Comprehensive Tests (examples/comprehensive/) + +| File | Tests | +|------|-------| +| `sign_all.c` | Sign1 + multi-signer matrix (~61 tests) | +| `encrypt_all.c` | Encrypt0 + multi-recipient matrix (~23 tests) | +| `mac_all.c` | Mac0 + multi-recipient matrix (~32 tests) | +| `errors_all.c` | Error handling and edge cases (~19 tests) | + +### Scenario Examples (examples/scenarios/) + +| File | Scenario | +|------|----------| +| `firmware_update.c` | Post-quantum ML-DSA firmware signing with detached payload | +| `multi_party_approval.c` | Dual-control firmware approval (ES256 + ES384) | +| `iot_fleet_config.c` | Encrypted config push to IoT device fleet with multiple recipients | +| `sensor_attestation.c` | EAT-style attestation with replay protection via external AAD | +| `group_broadcast_mac.c` | Authenticated broadcast to multiple subscribers | + +--- + +## Integration Notes + +### Minimal Integration + +For a minimal COSE integration, you need: +1. `include/wolfcose/wolfcose.h` +2. `include/wolfcose/visibility.h` +3. `src/wolfcose.c` +4. `src/wolfcose_cbor.c` +5. `src/wolfcose_internal.h` + +### CBOR-Only Integration + +If you only need CBOR (no COSE): +1. `include/wolfcose/wolfcose.h` (for CBOR types) +2. `src/wolfcose_cbor.c` + +No wolfCrypt dependency required for CBOR-only. + +### Production Builds + +Do NOT include in production firmware: +- `tools/` directory +- `examples/` directory +- `tests/` directory + +--- + +## See Also + +- [[Getting Started]]: Build instructions +- [[API Reference]]: Function documentation +- [[Testing]]: Test organization diff --git a/docs/README.md b/docs/README.md new file mode 100644 index 0000000..dc20216 --- /dev/null +++ b/docs/README.md @@ -0,0 +1,16 @@ +# 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/Testing.md b/docs/Testing.md new file mode 100644 index 0000000..fe6f8a6 --- /dev/null +++ b/docs/Testing.md @@ -0,0 +1,186 @@ +# Testing + +wolfCOSE includes comprehensive testing infrastructure for unit tests, algorithm coverage, code coverage, and failure injection testing. Code coverage is enforced by CI: `wolfcose.c` requires 99% minimum and `wolfcose_cbor.c` requires 100%. These thresholds are validated on every push and PR to ensure coverage doesn't regress. + +## Running Tests + +### Basic Unit Tests + +```bash +make test +``` + +This runs the full test suite including: +- CBOR encoding/decoding tests (RFC 8949 Appendix A vectors) +- COSE Sign1/Encrypt0/Mac0 tests +- COSE Sign/Encrypt/Mac multi-party tests +- Interoperability tests with COSE Working Group vectors + +### CLI Tool Tests + +```bash +make tool-test +``` + +Round-trip self-tests for all 17 supported CLI algorithms. Each algorithm is tested with key generation, operation, and verification. + +### Comprehensive Algorithm Tests + +```bash +make comprehensive +``` + +Runs ~240 algorithm combination tests covering: +- All signature algorithms with various payloads +- All encryption algorithms with various key sizes +- All MAC algorithms +- Multi-signer and multi-recipient combinations +- Error handling and edge cases + +### Scenario Examples + +```bash +make scenarios +``` + +Runs real-world scenario examples: +- Firmware signing with ML-DSA +- Multi-party approval workflows +- IoT fleet configuration +- Sensor attestation +- Group broadcast MAC + +--- + +## Code Coverage + +### Running Coverage + +```bash +make coverage +``` + +This compiles with gcov instrumentation and runs tests, producing coverage reports. + +### Coverage Targets + +| Component | Target | +|-----------|--------| +| `wolfcose.c` | 99% minimum | +| `wolfcose_cbor.c` | 100% minimum | + +### Coverage with Failure Injection + +```bash +make coverage-force-failure +``` + +This enables additional coverage by testing error paths that normally require wolfCrypt internal failures. + +--- + +## Force Failure Testing + +wolfCOSE includes a failure injection system for testing error paths that are difficult to reach through normal testing. + +The `WOLFCOSE_FORCE_FAILURE` build flag enables controlled injection of failures at specific points in the code. This allows testing of: + +- Crypto operation failures (signature, encryption, decryption, MAC) +- Key operation failures +- Memory/buffer errors +- Internal state errors + +### Production Builds + +The force failure system compiles out completely in production builds. When `WOLFCOSE_FORCE_FAILURE` is not defined: + +- All failure injection code is excluded +- `wolfForceFailure_Check()` always returns 0 +- No runtime overhead + +--- + +## CI Pipeline + +wolfCOSE runs the following CI checks on every push and pull request: + +### Build and Test Matrix + +| Environment | Compilers | +|-------------|-----------| +| Ubuntu (latest + 22.04) | GCC 10, 11, 12, 13, 14 | +| Ubuntu (latest + 22.04) | Clang 14, 15, 16, 17, 18 | +| macOS | Xcode default | + +### Test Stages + +1. **Build**: Compile library and tests +2. **Unit Tests**: Run CBOR and COSE test suites +3. **Comprehensive Tests**: ~240 algorithm combination tests +4. **Scenario Examples**: Real-world workflow tests +5. **Tool Tests**: CLI round-trip tests (17 algorithms) + +### Static Analysis + +| Tool | Purpose | +|------|---------| +| cppcheck | Static code analysis | +| Clang Static Analyzer | Data flow analysis | +| GCC `-fanalyzer` | GCC's built-in analyzer | +| Advanced Internal Static Analysis | Security Audit | +| In PR Opus 4.6 Diff review with wolfSSL internal review bot | Security Audit | + +### Coverity Scan + +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 + +``` +tests/ + test_cbor.c # CBOR vectors (RFC 8949 Appendix A) + round-trip + test_cose.c # COSE Sign1/Encrypt0/Mac0/Sign/Encrypt/Mac tests + test_interop.c # Interoperability tests with RFC vectors + test_main.c # Test harness (CI exit codes) + force_failure.c # Failure injection implementation + force_failure.h # Failure injection API + vectors/ # Test vectors from COSE Working Group +``` + +### Test Categories in test_cose.c + +| Category | Description | +|----------|-------------| +| Sign1 Tests | Single-signer signature creation and verification | +| Encrypt0 Tests | Symmetric encryption and decryption | +| Mac0 Tests | Symmetric MAC creation and verification | +| Sign Tests | Multi-signer messages | +| Encrypt Tests | Multi-recipient encryption | +| Mac Tests | Multi-recipient MAC | +| Key Tests | COSE_Key encoding and decoding | +| Error Tests | Invalid inputs, tampered messages | +| Detached Payload Tests | Messages with external payloads | +| External AAD Tests | Additional authenticated data | + +--- + +## Test Vectors + +The `tests/vectors/` directory contains test vectors from: +- COSE Working Group examples +- RFC 9052 examples +- Custom edge case vectors + +Vector format is typically CBOR diagnostic notation or hex dumps with expected outputs. + +--- + +## See Also + +- [[Getting Started]]: Build instructions +- [[Macros]]: Test configuration macros +- [[Project Structure]]: Source file layout diff --git a/docs/_Sidebar.md b/docs/_Sidebar.md new file mode 100644 index 0000000..2f13848 --- /dev/null +++ b/docs/_Sidebar.md @@ -0,0 +1,11 @@ +### Documentation + +- [[Home]] +- [[Getting Started]] +- [[Message Types]] +- [[Algorithms]] +- [[API Reference]] +- [[Macros]] +- [[Testing]] +- [[MISRA Compliance]] +- [[Project Structure]]