Skip to content

Commit

Permalink
style: run npx prettier . --write
Browse files Browse the repository at this point in the history
  • Loading branch information
aloisklink committed Jul 10, 2023
1 parent 287b679 commit fbd513e
Show file tree
Hide file tree
Showing 11 changed files with 96 additions and 58 deletions.
6 changes: 3 additions & 3 deletions .github/workflows/docs.yml
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ jobs:

- name: Install modules (CI-mode)
run: npm ci

- name: Lint
run: npm run lint

Expand All @@ -42,8 +42,8 @@ jobs:
needs: build-docs
# Grant GITHUB_TOKEN the permissions required to make a Pages deployment
permissions:
pages: write # to deploy to Pages
id-token: write # to verify the deployment originates from an appropriate source
pages: write # to deploy to Pages
id-token: write # to verify the deployment originates from an appropriate source
# Deploy to the github-pages environment
environment:
name: github-pages
Expand Down
17 changes: 13 additions & 4 deletions docs/capture.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,12 @@ title: Capture Service
The network capture service has the purpose of monitoring network traffic for each connected device. It can be configured to execute custom middlewares. The packet capture implements the actual network sniffing process. Currently, it uses the [libpcap library](https://github.com/the-tcpdump-group/libpcap). However, it also allows interfacing with [PF_RING](https://www.ntop.org/products/packet-capture/pf_ring/) or similar.

The capture service can be configured with the below options:

```ini
# absolute path to the capture SQLite db used by the middlewares
captureDbPath = "/path_to_capture/capture.sqlite"
# the capture filter for the libpcap library
# example filter="src net 10.0 and dst net 10.0"
# example filter="src net 10.0 and dst net 10.0"
filter = ""
# libpcap options, see https://www.tcpdump.org/manpages/pcap.3pcap.html
# if true, captures all data on the LAN interface
Expand All @@ -25,6 +26,7 @@ immediate = false
# Middlewares

The captured packet is sent to every configured middleware for additional processing. The user has the choice to develop her own middleware. The middleware API is defined in `middleware.h`:

```c
struct capture_middleware {
struct middleware_context *(*const init)(sqlite3 *db, char *db_path, struct eloop_data *eloop, struct pcap_context *pc);
Expand All @@ -33,13 +35,15 @@ struct capture_middleware {
const char *const name;
};
```

Every middleware needs to define three functions `init`, `process` and `free`.

- The `init` function initialises the middleware, configures the event loop structures and/or creates new tables in the capture database.
- The `process` function receives as input the captured packets and does the required processing.
- Finally, the `free` function frees the allocated memory and removes the created tables if needed.
- The `init` function initialises the middleware, configures the event loop structures and/or creates new tables in the capture database.
- The `process` function receives as input the captured packets and does the required processing.
- Finally, the `free` function frees the allocated memory and removes the created tables if needed.

To add a middleware, the user can create a subfolder in the [`src/capture/middlewares` folder](https://github.com/nqminds/edgesec/tree/main/src/capture/middlewares) with the name `example_middleware` and add the main include file `example_middleware.h` with the contents:

```c
#ifndef EXAMPLE_MIDDLEWARE_H
#define EXAMPLE_MIDDLEWARE_H
Expand All @@ -49,7 +53,9 @@ To add a middleware, the user can create a subfolder in the [`src/capture/middle
extern struct capture_middleware example_middleware;
#endif
```

and the main source file `example_middleware.c` with the contents:

```c
#include <sqlite3.h>
#include <libgen.h>
Expand Down Expand Up @@ -116,7 +122,9 @@ struct capture_middleware example_middleware = {
.name = "example middleware",
};
```
Then the user needs to add the option `option(USE_EXAMPLE_MIDDLEWARE "Use the example middleware" ON)` in the root `CMakeLists.txt` and subsequently add the lines:
```cmake
# write your CMakeLists.txt file to compile your middleware
add_subdirectory(./middlewares/example_middleware)
Expand All @@ -130,6 +138,7 @@ if (USE_EXAMPLE_MIDDLEWARE)
)
endif ()
```

in `capture/CMakeLists.txt`.

The capture middleware will execute every defined middleware sequentially. First, it will execute the `init` functions. Then, for every packet it will execute all `process` functions and finally, it will run every `free` function.
34 changes: 21 additions & 13 deletions docs/crypt.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,47 +6,53 @@ title: Crypt Service
The crypt service service implements a key/value store for all other services to store and retrieve encrypted keys or data. To encrypt data the crypt service generates keys that are encrypted using the hardware secure element or a user supplied passphrase.

# Store DB

The crypt service is implemented as a sqlite database (the path is set by the `config.ini` parameter `cryptDbPath`), which contains two tables: `secrets` and `store`.

The schema for the secrets table is as follows:

```sql
CREATE TABLE secrets (id TEXT NOT NULL, value TEXT, salt TEXT, iv TEXT, PRIMARY KEY (id));
```

where `id` is the ID of the generated key, `value` is the value of the key, `iv` the initial value (IV) used to encrypt and decrypt the key and `salt` is the salt parameter.

An example of the secrets table row is given below:

|ID|VALUE|SALT|IV|
|--|-----|----|--|
|master|LbknNO6o+s+u1b4wg9eGzQjHCanicVtDlDJBWZ0u4VaV25oIUCt1b5bthzLwhQO0|Z95m5G/+jgb3ga0dufa//w|hka2MmSUkJUJBf7TQMYnug|
|rest|a2UiZR/DLYb3hX61ZQ7Mb/vdVVIchJzkuNnoIhLDCHXe9453IlWjOfOymodUZIsq|RLdlnafYj7279lne7A5UoA|lgTKNxgxbeCxg4VySS/7vw|
|94:b9:7e:15:47:95|lPVf5wqMnb9+8Q8Cik5oetOI9MfA6qjPm1tKTR3WGPWgZYtaybEeDKWGX/x4EUUB|gFvI5tfeHANOafJlFsHXpg|mH2yeX/FEvJd1ilg25Zwcg|
| ID | VALUE | SALT | IV |
| ----------------- | ---------------------------------------------------------------- | ---------------------- | ---------------------- |
| master | LbknNO6o+s+u1b4wg9eGzQjHCanicVtDlDJBWZ0u4VaV25oIUCt1b5bthzLwhQO0 | Z95m5G/+jgb3ga0dufa//w | hka2MmSUkJUJBf7TQMYnug |
| rest | a2UiZR/DLYb3hX61ZQ7Mb/vdVVIchJzkuNnoIhLDCHXe9453IlWjOfOymodUZIsq | RLdlnafYj7279lne7A5UoA | lgTKNxgxbeCxg4VySS/7vw |
| 94:b9:7e:15:47:95 | lPVf5wqMnb9+8Q8Cik5oetOI9MfA6qjPm1tKTR3WGPWgZYtaybEeDKWGX/x4EUUB | gFvI5tfeHANOafJlFsHXpg | mH2yeX/FEvJd1ilg25Zwcg |

The `value`, `salt` and `iv` are base64 encoded.

When a user or service wants to store a key/value, they will need to provide an ID for the key that will be used to encrypt/decrypt the user's value. If such an ID does not exist in the secrets table, the service will randomly generate one and encrypt it using the hardware secure element or the user supplied passphrase. When the user provides the passphrase, the service will generate an encryption key using the `salt` and [Password-Based Key Derivation Function 2 (PBKDF2)](https://en.wikipedia.org/wiki/PBKDF2). The derived key is not stored on the device. If the user instead uses the hardware secure element, the key derivation, encryption and decryption is done in secure memory.

Each key/value pair is stored in the store table with the following schema:

```sql
CREATE TABLE store (key TEXT NOT NULL, value TEXT, id TEXT, iv TEXT, PRIMARY KEY (key));
```

where `key` is the key for the value, `value` is the value to be stored, `id` is the key id used to encrypt/decrypt the value and `iv` is the IV used to encrypt/decrypt the value.

An example of the store table rows is given below.

|KEY|VALUE|ID|IV|
|---|-----|--|--|
|7815f8ce-57b8-49c8-9121-5b98986cbccd|GCM564Ugwyh0bW3f4JuFkw|master|Ja0pz9cdH7p3Q+BBP2MIrw|
|db07c38a-2842-4f45-9672-74d57ec99e63|23cHWe6r033czxopWsv6Ng|master|FU7hUGGbifro65cv0u0OwQ|
|1a35f54d-c5f9-4072-85b0-4b40f8fb4a14|LR3iRw6SrN/pWKSTJvNtrA|master|x9hFentG2Q6iynHXCk2ktA|
|831ffbb1-2e79-422a-bdad-e9e96a56d568|CdoxKK4PbDvWD9cOdRcTXQ|master|RHR1AGsjpWVHDR4VN2PiLA|
| KEY | VALUE | ID | IV |
| ------------------------------------ | ---------------------- | ------ | ---------------------- |
| 7815f8ce-57b8-49c8-9121-5b98986cbccd | GCM564Ugwyh0bW3f4JuFkw | master | Ja0pz9cdH7p3Q+BBP2MIrw |
| db07c38a-2842-4f45-9672-74d57ec99e63 | 23cHWe6r033czxopWsv6Ng | master | FU7hUGGbifro65cv0u0OwQ |
| 1a35f54d-c5f9-4072-85b0-4b40f8fb4a14 | LR3iRw6SrN/pWKSTJvNtrA | master | x9hFentG2Q6iynHXCk2ktA |
| 831ffbb1-2e79-422a-bdad-e9e96a56d568 | CdoxKK4PbDvWD9cOdRcTXQ | master | RHR1AGsjpWVHDR4VN2PiLA |

The `value` and `iv` are base64 encoded.

Each row of the store DB contains the `id` of the key that was used to encrypt/decrypt the `value`. The encryption algorithm used is AES 256 CBC.

# Secure element
In order to enable the use of secure element one needs to set the `USE_CRYPTO_SERVICE` and `USE_*_HSM` options in CMake when compiling edgesec, which corresponds to a particular implementation of the secure element API.

In order to enable the use of secure element one needs to set the `USE_CRYPTO_SERVICE` and `USE_*_HSM` options in CMake when compiling edgesec, which corresponds to a particular implementation of the secure element API.

In order to add an aditional implementation of a secure hardware element, one can use the generic driver interface `generec_hsm_drive.h` as a template. The generic driver interface defines the context:

Expand All @@ -55,7 +61,9 @@ struct hsm_context {
void *hsm_ctx;
};
```

that is passed to the init and encrypt/decrypt functions as follows:

```c
struct hsm_context *init_hsm(void);
int close_hsm(struct hsm_context *context);
Expand All @@ -64,4 +72,4 @@ int encrypt_hsm_blob(struct hsm_context *context, uint8_t *in, size_t in_size, u
int decrypt_hsm_blob(struct hsm_context *context, uint8_t *in, size_t in_size, uint8_t **out, size_t *out_size);
```
The developer will have to provide a tailored implementation for the above functions in order to use a particular hardware secure element. An example is provided in `zymkey4_driver.h`.
The developer will have to provide a tailored implementation for the above functions in order to use a particular hardware secure element. An example is provided in `zymkey4_driver.h`.
15 changes: 9 additions & 6 deletions docs/management.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ The subnet configuration is given in `config.ini` as follows:
# Used on OpenWRT systems to define the bridge prefix
bridgePrefix = "br"
# The prefix for the interface name that corresponds to a VLAN,
# for instance for VLAN 2 and `interfacePrefix = "br"`
# for instance for VLAN 2 and `interfacePrefix = "br"`
# the corresponding interface will be `br2`.
interfacePrefix = "br"
if0 = "0,10.0.0.1,10.0.0.255,255.255.255.0"
Expand All @@ -38,6 +38,7 @@ if8 = "8,10.0.8.1,10.0.8.255,255.255.255.0"
if9 = "9,10.0.9.1,10.0.9.255,255.255.255.0"
if10 = "10,10.0.10.1,10.0.10.255,255.255.255.0"
```

where `ifn` key enumerates parameters for each interface that will be created by the subnet service, where all parameters are separated by commas. The first parameter is the VLAN ID, the second parameter is the gateway IP, the third parameter is the broadcast IP and the fourth parameter is the netmask. For instance given `if8 = "8,10.0.8.1,10.0.8.255,255.255.255.0"` and `interfacePrefix = "br"` the created interface `br8` has the following parameters:

```console
Expand All @@ -64,15 +65,15 @@ The `config.ini` parameters for the RADIUS server are as follows:
[radius]
# The UDP port for the RADIUS server
port = 1812
# The IP of the client (in our case it is the software AP)
# The IP of the client (in our case it is the software AP)
# that will connect to the RADIUS server
clientIP = "127.0.0.1"
# The netmask of the client
clientMask = 32
# The IP of the RADIUS server to which it binds to
serverIP = "127.0.0.1"
serverMask = 32
# The key used to encrypt the communication between the
# The key used to encrypt the communication between the
# client and RADIUS server
secret = "radius"
```
Expand Down Expand Up @@ -116,6 +117,7 @@ loggerSyslogLevel = 0
ignoreBroadcastSsid = 0
wpaPskRadius = 2
```

where for OpenWRT systems `apBinPath=/sbin/wifi` points to the WIFI configuration script and `device = "radio1"` is the parameter denoting the index of the radio used to configure the WIFI modem. The name of the WIFI AP is given by the paremeter `ssid`. If `generateSsid` from `config.ini` is set ot `true`, the `ssid` parameter will be assign to the hostname of the router. The default encryption key for the WIFI is given by the parameter `wpaPassphrase`. This encryption key will be shared by all connected WIFI devices, if the RADIUS server doesn't assign a different encryption key for a specific device.

All the remaining parameters `vlanTaggedInterface`, `hwMode`, `channel`, `wmmEnabled`, `authAlgs`, `wpa`, `wpaKeyMgmt`, `rsnPairwise`, `ctrlInterface`, `macaddrAcl`, `dynamicVlan`, `vlanFile`, `loggerStdout`, `loggerStdoutLevel`, `loggerSyslog `, `loggerSyslogLevel`, `ignoreBroadcastSsid` and `wpaPskRadius` are similar to the ones defined for [hostapd.conf](https://w1.fi/cgit/hostap/plain/hostapd/hostapd.conf).
Expand All @@ -130,15 +132,15 @@ The `config.ini` parameteres for the DHCP service are as follows:

```ini
[dhcp]
# The absolute path to the dnsmasq executable
# The absolute path to the dnsmasq executable
# (for OpenWRT systems this path is /etc/init.d/dnsmasq)
dhcpBinPath = "/usr/sbin/dnsmasq"
# The absolute path to the dnsmasq configuration file
# The absolute path to the dnsmasq configuration file
# (for non OpenWRT this file is generated by edgesec)
dhcpConfigPath = "/tmp/dnsmasq.conf"
# The absolute path to the IP leases file
dhcpScriptPath = "/tmp/dnsmasq_exec.sh"
# The absolute path to the DHCP control script file, which has the role of
# The absolute path to the DHCP control script file, which has the role of
# sending the allocated IP address to the edgesec
dhcpLeasefilePath = "/tmp/dnsmasq.leases"
dhcpRange0 = "0,10.0.0.2,10.0.0.254,255.255.255.0,24h"
Expand All @@ -153,6 +155,7 @@ dhcpRange8 = "8,10.0.8.2,10.0.8.254,255.255.255.0,24h"
dhcpRange9 = "9,10.0.9.2,10.0.9.254,255.255.255.0,24h"
dhcpRange10 = "10,10.0.10.2,10.0.10.254,255.255.255.0,24h"
```

where the `dhcpRange*` parameter configures the IP allocation settings for the DHCP server. The first setting denotes the VLAN index. The second and third settings the pool of IP addresses. The last setting denotes the lease time for the allocated IP address.

For `dnsmasq` the control script file is as follows:
Expand Down
14 changes: 8 additions & 6 deletions docs/reflector.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,19 +6,21 @@ title: mDNS Reflector Service
The mDNS reflector service forwards mDNS packets between subnets. It listens to mDNS queries and answers and rebroadcasts them on the available subnets.

# Operation

The mDNS reflector services contains three componets:
1. mDNS packet listener
2. mDNS packet decoder
3. mDNS packet forwarder

1. mDNS packet listener
2. mDNS packet decoder
3. mDNS packet forwarder

The mDNS packet listener captures UDP data packets embedded in IP4 or IP6 packets. The UDP data packets are subsequently decoded in order to retrieve the queries and answers fields. The broadcasted/quiered mDNS adresses and the corresponding IP4/IP6 addresses are stored in memory. These addresses are later used for bridge connections between devices across subnets. Finally, the mDNS packet is forwarded to all available subnets. The main reasoning for forwarding the mDNS packet is that when a device broadcast its address, the mDNS packet doesn't cross its allocated subnet (see [RFC6762](https://datatracker.ietf.org/doc/html/rfc6762)).

The options `mdnsReflectIp4` and `mdnsReflectIp6` from `config.ini` if set to `true` will configure the mDNS service to forward mDNS IP4 and IP6 packets, respectively. The options `mdnsFilter = "src net 10.0 and dst net 10.0"` set the filter for the mDNS capture to intercept only packets that correspond only to the subnet activity, i.e., inter-device communication.

The mDNS reflector service will automatically create a bridge between two devices across two different subnets, if the following conditions are met:
- At least one device in the bridge broadcasted its mDNS address,
- At least one device in the bridge whishes to connect to the IP address that corresponds to the broadcasted mDNS adrress.

- At least one device in the bridge broadcasted its mDNS address,
- At least one device in the bridge whishes to connect to the IP address that corresponds to the broadcasted mDNS adrress.

# Example

Expand All @@ -32,4 +34,4 @@ The device `A` is broadcasting its mDNS address `devicea.local`. However, due to

As a result, device `B` will infer that the IP4 address of `devicea.local` is `10.0.2.34`. Subsequently, if device `B` wants to connect to device `A`, the mDNS reflector will create a bridge between `A` and `B` (see figure below).

![Bridge](/img/reflector-bridge.svg)
![Bridge](/img/reflector-bridge.svg)
1 change: 1 addition & 0 deletions docs/supervisor.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ supervisorControlPort = 32001
# Sets the absolute path to the UNIX domain socket
supervisorControlPath = "/tmp/edgesec-control-server"
```

For instance by using the `netcat` utility one can send the `GET_MAP 11:22:33:44:55:66` command to the supervisor's UNIX domain socket located at `/tmp/edgesec-control-server` as follows:

```bash
Expand Down
3 changes: 1 addition & 2 deletions docusaurus.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -68,8 +68,7 @@ module.exports = {
routeBasePath: "/docs", // set to "/" if you want to link directly to docs
sidebarPath: require.resolve("./sidebars.js"),
// Please change this to your repo.
editUrl:
"https://github.com/nqminds/edgesec.info/edit/main/",
editUrl: "https://github.com/nqminds/edgesec.info/edit/main/",
remarkPlugins: [
// renders all mermaid code-blocks found in markdown files
[require("remark-mermaid-dataurl"), {}],
Expand Down
9 changes: 8 additions & 1 deletion sidebars.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,13 @@
module.exports = {
someSidebar: {
Introduction: ["motivation", "supervisor", "management", "capture", "reflector", "crypt"],
Introduction: [
"motivation",
"supervisor",
"management",
"capture",
"reflector",
"crypt",
],
Development: ["compilation", "running", "config", "issues"],
Deployment: ["packages", "deployment", "devices"],
},
Expand Down
Loading

0 comments on commit fbd513e

Please sign in to comment.