- When to use
- Intellectual property
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.
When to use
This code implements the same protocol as
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:
This will output, into the
build/symkey folder, a directory structure
. ├── 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:
and where needed
make test. Output in this case will be in
libe4 can be integrated into your application as follows:
- You should add
build/mode/includeto your include path, e.g.
- You should link with the static library.
You may then use
e4 in your code with the include:
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
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
e4.h. If you do this, be sure to
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
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.