# 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
}
...
```


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://libec.erayd.net/channels.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
