# esp-cose
COSE (RFC 8152 / 9052) for ESP32. Uses mbedtls PSA Crypto and tinycbor.
## Install
```yaml
dependencies:
matterizelabs/esp-cose: "1.0.0"
```
## API
### Key setup
```c
#include <cose.h>
cose_key_t key;
cose_key_init(&key);
// Ed25519 signing key
key.kty = KEY_TYPE_OKP;
key.crv = CURVE_ED25519;
key.d = private_seed;
key.d_len = 32;
key.x = public_key;
key.x_len = 32;
// symmetric key (AES, HMAC)
cose_key_t sk;
cose_key_init(&sk);
sk.kty = KEY_TYPE_SYMMETRIC;
sk.k = key_bytes;
sk.k_len = 16;
cose_key_free(&key); // deallocate when done
```
### COSE_Sign1
```c
uint8_t out[1024]; size_t out_len;
cose_sign1_create((const uint8_t *)"payload", 7,
&ed_key, ALG_EDDSA,
(const uint8_t *)"ext_aad", 8, // external AAD
NULL, 0, // KID
out, &out_len, sizeof(out));
```
```c
uint8_t payload[256]; size_t pl = sizeof(payload);
cose_sign1_verify(msg, msg_len, &verif_key,
(const uint8_t *)"ext_aad", 8,
payload, &pl, sizeof(payload));
```
Detached mode (payload not embedded):
```c
cose_sign1_create_detached(payload, payload_len, &key, ALG_EDDSA,
NULL, 0, out, &out_len, sizeof(out));
cose_sign1_verify_detached(msg, msg_len, &key, payload, payload_len,
NULL, 0);
```
### COSE_Sign (multi-signer)
```c
cose_sign_signer_t signers[] = {
{&key1, ALG_EDDSA, NULL, 0},
{&key2, ALG_ES256, kid, kid_len},
};
cose_sign_create(payload, payload_len, signers, 2,
NULL, 0, out, &out_len, sizeof(out));
cose_sign_verify(msg, msg_len, &key, ALG_EDDSA,
NULL, 0, payload, &pl, sizeof(payload));
```
### COSE_Encrypt0 (AEAD)
```c
cose_encrypt0_create(pt, pt_len, &sym_key, ALG_AES_GCM_128,
NULL, 0, false, out, &out_len, sizeof(out));
cose_encrypt0_decrypt(msg, msg_len, &sym_key, ALG_AES_GCM_128,
NULL, 0, pt, &ptl, sizeof(pt));
```
### COSE_Encrypt (multi-recipient)
```c
cose_encrypt_recipient_t r[] = {
{.alg = ALG_A256KW, .key = &kw_key},
};
cose_encrypt_create(pt, pt_len, ALG_AES_GCM_128, r, 1,
NULL, 0, out, &out_len, sizeof(out));
cose_key_t keys[] = {kw_key};
cose_encrypt_decrypt(msg, msg_len, keys, 1,
NULL, 0, pt, &ptl, sizeof(pt));
```
### COSE_Mac0 / COSE_Mac
```c
cose_mac0_create(payload, payload_len, &hmac_key, ALG_HMAC_256_256,
NULL, 0, out, &out_len, sizeof(out));
cose_mac0_verify(msg, msg_len, &hmac_key, NULL, 0, pt, &pl, sizeof(pt));
```
```c
cose_mac_recipient_t r[] = {{&kw_key, ALG_A256KW, NULL, 0}};
cose_mac_create(payload, payload_len, ALG_HMAC_256_256, r, 1,
NULL, 0, out, &out_len, sizeof(out));
cose_mac_verify(msg, msg_len, keys, 1, NULL, 0, pt, &pl, sizeof(pt));
```
### Countersignature (RFC 9338)
```c
cose_sign1_with_cs0(payload, payload_len,
&signer_key, ALG_EDDSA,
&cs_key, ALG_EDDSA,
NULL, 0, out, &out_len, sizeof(out));
cose_sign1_verify_cs0(msg, msg_len, &signer_vk, &cs_vk,
NULL, 0, pt, &pl, sizeof(pt));
```
## Algorithms
| Algorithm | Constant |
|---|---|
| EdDSA | `ALG_EDDSA` |
| ES256 | `ALG_ES256` |
| ES384 | `ALG_ES384` |
| ES512 | `ALG_ES512` |
| AES-GCM-128/192/256 | `ALG_AES_GCM_128/192/256` |
| AES-CCM-* | `ALG_AES_CCM_*` |
| ChaCha20-Poly1305 | `ALG_CHACHA20_POLY1305` |
| HMAC-256-64/256 | `ALG_HMAC_256_64/256` |
| HMAC-384-384 | `ALG_HMAC_384_384` |
| HMAC-512-512 | `ALG_HMAC_512_512` |
| AES-MAC-* | `ALG_AES_MAC_*` |
| A128/192/256KW | `ALG_A128KW/192/256KW` |
| direct | `ALG_DIRECT` |
## Error codes
| Value | Constant |
|---|---|
| 0 | `COSE_OK` |
| -1 | `COSE_ERR_PARSE` |
| -2 | `COSE_ERR_FORMAT` |
| -3 | `COSE_ERR_CRYPTO` |
| -5 | `COSE_ERR_NOMEM` |
| -6 | `COSE_ERR_ALG` |
| -7 | `COSE_ERR_ARG` |
| -8 | `COSE_ERR_BUF` |
| -10 | `COSE_ERR_NOTFOUND` |
## Example
See [esp-cose-examples](https://github.com/matterizelabs/esp-cose-examples) for a complete CoAP-based peer-to-peer demo with Sign1, Encrypt0, Mac0, Sign, Encrypt, Mac, and Countersignature.
idf.py add-dependency "matterizelabs/esp-cose^1.0.6"