> For the complete documentation index, see [llms.txt](https://libec.erayd.net/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://libec.erayd.net/channels.md).

# Channels

Libec uses channels to implement secure communication between two entities. Data is encrypted and protected with a MAC.

## API

* [ec\_channel\_clean()](/channels.md#ec-channel-clean)
* [ec\_channel\_init()](/channels.md#ec-channel-init)
* [ec\_channel\_start()](/channels.md#ec-channel-start)
* [ec\_channel\_encrypt()](/channels.md#ec-channel-encrypt)
* [ec\_channel\_decrypt()](/channels.md#ec-channel-decrypt)
* [ec\_channel\_remote()](/channels.md#ec-channel-remote)

### ec\_channel\_clean()

\`void ec\_channel\_clean(ec\_channel\_t \*ch);

Clean a previously used channel for reuse or free. Unlocks locked memory and zeros entire structure. Should be run once a channel is no longer required, before disposing of the channel.

```c
#include <ec.h>
...
ec_channel_clean(ch);
...
```

### ec\_channel\_init()

`ec_err_t ec_channel_init(ec_channel_t *ch, ec_cert_t *c, ec_ctx_t *ctx, unsigned char *dh);`

Initialise a channel and generate a signed Diffie-Hellman packet to pass to the remote endpoint. Returns zero on success, a nonzero error code otherwise. Once the channel is no longer required, it should be scrubbed using `ec_channel_clean()`.

`ctx` should point to a context where the remote certificate can be found, and will be used for validation purposes - if trust chain checks are performed, then those certificates will also need to be available.

`c` is the certificate used as the local endpoint. This certificate does *not* need to be available in `ctx`.

Data to be passed to the remote endpoint (the negotiation packet) will be stored in `dh`, which should be a buffer of at least `EC_CHANNEL_DH_BYTES` bytes. The contents of this buffer should be provided to `ec_channel_start()` on the remote end.

```c
#include <ec.h>
...
ec_channel_t *ch;
unsigned char dh[EC_CHANNEL_DH_BYTES];
if(ec_channel_init(ch, c, ctx, dh) != 0) {
    //init failed
}
...
```

### ec\_channel\_start()

`ec_err_t ec_channel_start(ec_channel_t *ch, unsigned char *dh, int checks);`

Finish Diffie-Hellman negotiation and finalise channel setup. Returns zero on success, a nonzero error code otherwise.

`dh` should contain the negotiation packet generated by `ec_channel_init()` on the remote end.

`checks` is a bitfield determining which checks should be run on the remote certificate. All checks must pass for channel setup to complete successfully. `EC_CHECK_CERT` and `EC_CHECK_SIGN` will always be tested, whether or not they are set.

```c
#include <ec.h>
...
if(ec_channel_start(ch, dh, EC_CHECK_ALL) != 0) {
    //negotiation failed
}
...
```

### ec\_channel\_encrypt()

`ec_err_t ec_channel_encrypt(ec_channel_t *ch, unsigned char *buf, size_t len,`\
`unsigned char *mac, uint64_t *ctr);`

Encrypt a buffer, for later decryption by the other end of a channel. Returns zero on success, a nonzero error code otherwise.

A MAC (`EC_CHANNEL_MAC_BYTES` bytes) for the message will be stored in `*mac`, and the message sequence number will be stored in `*ctr` if `ctr` is not NULL.

```c
#include <ec.h>
...
unsigned char mac[EC_CHANNEL_MAC_BYTES];
uint64_t ctr;
if(ec_channel_encrypt(ch, buf, buf_length, mac, &ctr) != 0) {
    //encryption failed
}
...
```

### ec\_channel\_decrypt()

`ec_err_t ec_channel_decrypt(ec_channel_t *ch, unsigned char *buf, size_t len,`\
`unsigned char *mac, uint64_t ctr);`

Decrypt a buffer previously encrypted by the other end of the channel. Returns zero on success, a nonzero error code otherwise.

`mac` should be the MAC generated by the other end of the channel using `ec_channel_encrypt()`.

If messages are not decrypted in linear order, then `ctr` should be set to the sequence number of the message being decrypted. Otherwise, this can be left at zero, and it will be set automatically.

```c
#include <ec.h>
...
if(ec_cert_decrypt(ch, buf, buf_length, mac, 0) != 0) {
    //decryption failed
}
...
```

### ec\_channel\_remote()

`ec_cert_t *ec_channel_remote(ec_channel_t *ch);`

Get the certificate for the remote channel endpoint. Returns NULL on failure.

```c
#include <ec.h>
...
ec_cert_t *c = ec_channel_remote(ch);
if(c == NULL) {
    //unable to get remote certificate
}
...
```
