# wolfcose
Safe Rust API for wolfSSL wolfCOSE.
This crate wraps the complete public wolfCOSE C API while keeping raw FFI in
`wolfcose-sys`. The default build vendors wolfCOSE and pulls/builds wolfSSL
from source through `wolfcose-sys`.
wolfCOSE is GPL-3.0-or-later. Contact wolfSSL for commercial licensing.
## API groups
- Serde-like CBOR `to_vec` / `to_slice` / `from_slice` helpers with
`CborSerialize` and `CborDeserialize` traits.
- Builder APIs for COSE_Sign1, COSE_Sign, COSE_Encrypt0, COSE_Encrypt,
COSE_Mac0, and COSE_Mac.
- Typed header maps and parsed COSE message envelopes for inspection before
verification/decryption.
- Symmetric key builders and typed COSE_Key metadata views.
- CBOR encode/decode/skip/peek, including optional float helpers.
- COSE_Key initialization, symmetric key ownership, CBOR encode/decode, and raw
wolfCrypt key attachment helpers for ECC, Ed25519, Ed448, Dilithium, and RSA.
- COSE_Sign1 sign/verify and COSE_Sign multi-signer sign/verify.
- COSE_Encrypt0 encrypt/decrypt and COSE_Encrypt multi-recipient encrypt/decrypt.
- COSE_Mac0 create/verify and COSE_Mac multi-recipient create/verify.
Symmetric key material is owned safely by `CoseKey`. Asymmetric wolfCrypt key
objects are caller-owned by wolfCOSE design, so `CoseKey` exposes explicit
`unsafe` raw attachment methods with documented lifetime requirements.
Most operations have both caller-buffer APIs (`*_into`) and allocation-friendly
helpers (`*_to_vec`).
## Builders and keys
Builder APIs wrap the lower-level safe functions and keep attached/detached
payload selection explicit:
```rust
use wolfcose::{Algorithm, CoseKeyBuilder, Mac0Builder, PayloadMode};
let key = CoseKeyBuilder::symmetric([0x33u8; 32])
.algorithm(Algorithm::HMAC256)
.kid(b"kid-1")
.build()?;
let message = Mac0Builder::new()
.key(&key)
.algorithm(Algorithm::HMAC256)
.kid(b"kid-1")
.payload(PayloadMode::Attached(b"hello wolfCOSE"))
.mac_to_vec()?;
# let _ = message;
# Ok::<(), wolfcose::Error>(())
```
`SymmetricKey` owns raw symmetric material with optional `alg` and `kid` hints.
`CoseKeyView` exposes typed metadata from a `CoseKey` without taking ownership of
raw wolfCrypt key objects.
## Messages and headers
`HeaderMap`, `HeaderLabel`, and `HeaderValue` model common COSE headers while
preserving unknown integer and text labels. Parsed message envelopes such as
`CoseSign1Message`, `CoseEncrypt0Message`, and `CoseMac0Message` expose
protected/unprotected headers, attachment state, counts for signers/recipients,
and the original raw bytes.
```rust
let parsed = wolfcose::CoseMac0Message::parse(&message)?;
let alg = parsed.protected().algorithm();
# let _ = alg;
# Ok::<(), wolfcose::Error>(())
```
## Serialization
The serializer layer is intentionally serde-like but does not require the
external `serde` crate:
```rust
use wolfcose::{from_slice, to_vec};
let encoded = to_vec(&(true, 7u8, "wolfCOSE"))?;
let decoded: (bool, u8, String) = from_slice(&encoded)?;
# Ok::<(), wolfcose::Error>(())
```
The default `derive` feature also provides annotation macros:
```rust
use wolfcose::{from_slice, to_vec, CborDeserialize, CborSerialize};
#[derive(CborSerialize, CborDeserialize)]
struct Device {
id: u32,
#[cbor(rename = "kid")]
key_id: String,
#[cbor(default)]
note: String,
#[cbor(skip)]
cache: Vec<u8>,
}
let encoded = to_vec(&Device {
id: 7,
key_id: "sensor-a".to_owned(),
note: String::new(),
cache: Vec::new(),
})?;
let decoded: Device = from_slice(&encoded)?;
# Ok::<(), wolfcose::Error>(())
```
Named structs serialize as CBOR maps keyed by field name, tuple structs serialize
as arrays, unit structs serialize as null, and enums serialize as externally
tagged one-entry maps. Supported attributes include `rename`, `rename_all =
"snake_case"`, `transparent`, `default`, `skip`, `skip_serializing_if`, and
`with`.
Use `ByteStr` / `ByteBuf` for CBOR byte strings. `Vec<T>` serializes as a CBOR
array, matching serde's sequence behavior.
`CborSerializer` also has `sequence` and `map_entries` helpers, and
`CborItemReader` provides non-async top-level CBOR item reading over a supplied
memory buffer.
## Errors and features
Existing APIs return `Result<T, Error>`. Opt-in detailed decoding is available
through `from_slice_detailed`, `DetailedError`, `CborErrorKind`,
`CoseErrorKind`, and `ErrorContext`.
The default feature set is `std`, `alloc`, `vendored`, `full`, and `derive`.
The `alloc` feature marks allocation-backed APIs such as builders, typed header
maps, parsed messages, and owned CBOR values. Build and FFI behavior still
depends on `wolfcose-sys` features.
The crate also supports a true no-std/no-alloc build:
```bash
cargo check -p wolfcose --no-default-features --features "vendored full"
```
In no-alloc mode, use the raw CBOR encoder/decoder, primitive serializer traits,
borrowed byte strings, algorithm/type constants, errors, stream item reader, and
`wolfcose::raw`. Builders, owned keys, parsed message envelopes, dynamic CBOR
values, and `*_to_vec` helpers require `alloc`.
`Algorithm` exposes metadata helpers such as `class`, `key_bits_hint`,
`iv_len_hint`, `is_signing`, `is_encryption`, `is_mac`, and
`is_key_management`. Runtime availability still depends on the linked wolfSSL
and wolfCOSE configuration.