This repository provides the libe4
C library, a client library for
Teserakt's E4, and end-to-end encryption and
key management framework for MQTT and other publish-subscribe protocols.
libe4
defines a simple interface for encryption and decryption of messages.
int e4c_protect_message(uint8_t *ciphertext, size_t ciphertext_max_len, size_t *ciphertext_len, const uint8_t *message, size_t message_len, const char *topic_name, e4storage *storage, const uint32_t proto_opts);
- this function takes a message to be protected and a "topic" for which it should be protected and returns ciphertext that can be sent using your messaging layer.int e4c_unprotect_message(uint8_t *message, size_t message_max_len, size_t *message_len, const uint8_t *ciphertext, size_t ciphertext_len, const char *topic_name, e4storage *storage, const uint32_t proto_opts);
This function performs the reverse of the protect function.
We talk of message protection instead of just encryption because the protection operation includes also authentication and replay defense.
E4's server (C2) is necessary to send control messages and manage a fleet of clients through GUIs, APIs, and automation components. The server can for example deploy key rotation policies, grant and revoke rights, and enable forward secrecy.
Please contact us to request access to a private instance of the server, or test the limited public version. Without the C2 server, the E4 client library can be used to protect messages using static keys, manually managed.
This code implements the same protocol as e4go
.
If you are using a system that can support projects written in Golang, you
may prefer to benefit from the security and reliability of the language
instead of using C code.
This project is aimed at cases that have very small memory footprints, cannot tolerate stop-the-world garbage collection (i.e. realtime applications) or cannot run Golang code.
libe4
is designed only to include those components that are necessary for
a given mode to run. In particular, for low end devices using only symmetric
encryption, public key variants of the code should not be used.
libe4
can be compiled as follows:
CONF=symkey make
This will output, into the build/symkey
folder, a directory structure
as follows:
.
├── include
│ └── e4
│ ├── crypto
│ │ ├── aes256enc.h
│ │ ├── aes_siv.h
│ │ ├── curve25519.h
│ │ ├── ed25519.h
│ │ ├── fixedint.h
│ │ ├── selftest.h
│ │ ├── sha3.h
│ │ ├── sha512.h
│ │ └── xed25519.h
│ ├── e4.h
│ ├── inline.h
│ ├── internal
│ │ ├── e4c_pk_store_file.h
│ │ └── e4c_store_file.h
│ ├── pstdint.h
│ ├── stdint.h
│ ├── strlcpy.h
│ └── util.h
├── lib
│ └── libe4.a
Tests can be built with the following command:
CONF=symkey make testbuild
and the following command will build and execute tests in one pass
CONF=symkey make test
Users who wish to build the pubkey variant should run:
CONF=pubkey make
and where needed make test
. Output in this case will be in build/pubkey
.
Once compiled, libe4
can be integrated into your application as follows:
- You should add
build/mode/include
to your include path, e.g.-I$(E4DIR)/build/symkey/include
. - You should link with the static library.
You may then use e4
in your code with the include:
#include "e4/e4.h"
libe4
is designed to be used in environments that may not include any kind
of runtime or kernel. As a consequence, implementing persistent storage
will depend entirely on the capabilities of the hardware environment.
To overcome this, libe4
provides a e4storage
struct and corresponding
set of functions that are forward-declared in e4.h
. It also provides a
demonstration "file store" for both variants, and a "memory store" that is
not persistent.
The file store is enabled by default. To configure it explicitly, run:
CONF=symkey STORE=file make
To select memory storage, run
CONF=pubkey STORE=mem make
(this is also using public keys).
Alternatively, you may implement the storage APIs yourself. These are
described in e4.h
. If you do this, be sure to
pass
CONF=... STORE=none make
libe4
currently makes zero effort to be thread-safe and function calls are
not reentrant. This is because we wish to have zero dependencies on APIs
that provide this functionality and we have no knowledge of the target CPU
architecture.
libe4
respects environment variables such as CC
. You may therefore,
for example, cross compile for arm using something like:
CC=clang LD=clang \
E4_CFLAGS="--target=armv7m-linux-eabi" \
E4_LDFLAGS="--target=armv7m-linux-eabi" CSTD=c89 \
CC=clang LD=clang CONF=pubkey make
Or an appropriate way to target your cross compiler.
For the moment, Arduino and Android cross compile makefiles are in beta, but will be published publicly as soon as they are ready (they require a more complicated and specific use of make).
Before contributing, please read our CONTRIBUTING guide.
To report a security vulnerability (or potential vulnerability where private discussion is preferred) see SECURITY.
libe4 is copyright (c) Teserakt AG 2018-2020, and released under Apache 2.0 License, (see LICENSE). Portions are copyright other authors and licensed differently, please see OPENSOURCE.