Library and client implementation of EST Enrollment Protocol RFC 7030 https://www.rfc-editor.org/rfc/rfc7030.html
Update 27/12/23: thanks to https://github.com/61131 a first support for the RFC 8951 https://datatracker.ietf.org/doc/html/rfc8951 has been added.
Why another EST Client
EST Endpoints
Build 3.1. Linux/MacOS 3.2. Windows
Supported Backends
Custom TLS/X.509 Backend 5.1. Function map 5.2. Example
Usage 6.1. Client 6.1.1 Example 6.2. Library 6.2.1 With CMake 6.2.2 Without CMake
Tests
Logging
Custom parameters
Contribution
RFC Requirements
Actually, the standard reference implementation https://github.com/cisco/libest is very complex (Android support, BRSKI support, ...). Another problem with libest is the OpenSSL library used to implements all crypto capabilities because is the only supported library and the references are scattered in the code so is't easy to port to another library.
In the IoT world, we have devices with different SSL libraries (e.g. WolfSSL, BoringSSL, MbedTLS...) or different platforms that needs non-standard compilation methods or build chainsd (e.g. FreeRTOS and some market PLCs).
To support different platforms and libraries we need a 'pluggable' and configurable client.
/cacerts IMPLEMENTED /simpleenroll IMPLEMENTED /simplereenroll IMPLEMENTED /fullcmc NOT IMPLEMENTED /csrattrs NOT IMPLEMENTED
Compile Dependencies:
** Note: all dependencies are downloaded automatically using git submodules.
Current cmake build configuration provides some default arguments you can on/off as you wish:
Setup cmake artifacts: If you want to change the build output directory update the -B flag.
cmake -Ssrc -Bbuild
Compile the code:
cd build make
** Note: at the end you will find the artifact build/rfc7030-est-client
Run unit tests:
./bin/rfc7030-est-client-tests
Run integration tests:
./bin/rfc7030-est-integration-tests
Here the table of native supported TLS/X.509 backends.
Name | Folder | Version |
---|---|---|
OpenSSL | src/openssl | >= 1.x |
As described in the general description, this EST implementation is agnostic regarding the runtime crypto library. If you need a non-compliant library you must create your backend following some rules and configuring the plugin.
The logic of the EST client is written in the src/lib folder but, to invoke the provided client with a backend, you need some additional operations, such as parse authentication certificates, parse certificate output result and other.
A new backend need to expose and implement ALL function definitions located in the header file src/lib/include/rfc7030.h
** Note: an example for OpenSSL is located in src/openssl/openssl_rfc.c
The core of the backend plugin is the config function map. Basically, is a set of function pointers used by the EST core library to invoke implementation-specific functions.
Two different maps are required:
These maps MUST be configured by the backend (for example see the src/openssl/openssl_rfc.c file) and ALL function MUST be implemented. There aren't optional functions.
For example, you want to add a myssl library implementation:
Create new folder:
src/myssl
Create new file:
src/myssl/myssl_rfc.c
** Note: this file must implement all functions definitions:
Create new cmake file:
src/myssl/myssl_est_client_library.cmake
This file must expose all headers and source files required by the backend implementation. An example is src/openssl/ossl_est_client_library.cmake.
Add the library to the src/CMakeLists.txt file: Please remember to add a new cmake option (disabled by default) to enable/disable the new backend. For this example could be
OPTION(USE_MYSSL "Compile using myssl backend" OFF)
** Note: search in the file for the ### BEGIN OPENSSL SECTION and replicate the OpenSSL section as example.
Prepare cmake with flags:
cmake -Ssrc -Bbuild -DUSE_MYSSL=ON -DUSE_OPENSSL=OFF
Build the code:
cd build make
Run unit tests:
./bin/rfc7030-est-client-tests
Run integration tests:
./bin/rfc7030-est-integration-tests
Due to the generic nature of this EST implementation, you have the freedom to choose the type of usage you want.
You can compile the project and generate the command line client, you can build your own client logic using another backend or you can use the low level library and build you entire client from scratch. In addition you can use the current client logic without all "cli" feature importing the code in your project.
Located in the src/client directory, this is a command line interface client. You can run
./rfc7030_est_client -h
to view the list of input parameters.
First of all, from the http://testrfc7030.com website you must download the server chain dstcax3.pem using the command: wget http://testrfc7030.com/dstcax3.pem
With the client you can run three main operations:
CACerts
This command request to the EST server the list of CA certificates. No authentication is required here.
./rfc7030-est-client -s testrfc7030.com \ -p 8443 \ --server-chain dstcax3.pem \ --output cachain.pem \ cacerts
Enroll
This command request to the EST Server the emission of a certificate providing a local csr (p10) file in PEM format. Here we need authentication:
Basic Auth
./rfc7030-est-client -s testrfc7030.com \ -p 8443 \ --server-chain dstcax3.pem \ --csr req.p10 \ --basic-auth "estuser:estpwd" \ --output-ca cachain.pem \ --output-crt enrolled.pem \ enroll
TLS Auth
./rfc7030-est-client -s testrfc7030.com \ -p 9443 \ --server-chain dstcax3.pem \ --csr req.p10 \ --p12 preenrollment.p12 \ --p12-password "12345" \ --output-ca cachain.pem \ --output-crt enrolled.pem \ enroll
Renew
This command request to the EST Server the emission of a certificate that renews an old one providing a local csr (p10) file in PEM format and the old certificate (and its key) in P12.
The syntax of the command is the same as the Enroll changing the p12 file and the last command renew.
If you don't want (o you can't) use the pre-compiled client or you want to include the EST client in your code, you can write your own using the EST core library.
This project is not developed with the idea to generate a shared or dynamic library. To address PLC or low level hardware implementations, the code MUST be compiled with the source code of the client. This makes the library compatible with FreeRTOS also.
The drawback is that you must clone this repo and add to your build toolchain all required headers and source files.
To use all library functions you need to include only one header file
#include <est.h>
and this provides to you the access to all low level functions (prefixed with est_xxx) and all low level "client" functions (prefixed with est_client_xxx).
** Note: see the src/openssl/openssl_rfc.c file to check how to use low level EST library functions.
If you are using cmake, you can add all required file using the provided cmake import file
include(${MODULE_ROOT_DIR}/src/lib/est_library.cmake)
** Note: this include provides to you cmake config some variables:
- EST_SRC
- EST_HEADERS
In addition, if you want to use an already implemented backend, you must add it in the same way. Here the example for OpenSSL:
include(${MODULE_ROOT_DIR}/src/openssl/ossl_est_client_library.cmake)
** Note: this include provides to you cmake config some variables:
- EST_OPENSSL_SRC
- EST_OPENSSL_SRC_TEST
- EST_OPENSSL_HEADERS
If you don't want to use cmake or you need another compile manager you can directly link all required headers and source files.
Set the include directory
src/lib/include src/third_party/picohttpparser
Set the src files to link
src/lib/cacerts.c src/lib/client.c src/lib/enroll.c src/lib/error.c src/lib/est.c src/lib/http.c src/lib/picohttp.c src/third_party/picohttpparser/picohttpparser.c
To link the selected backend you need to do the same.
./bin/rfc7030-est-client-tests
Run integration tests:
./bin/rfc7030-est-integration-tests
** Note: integration tests need internet connection to reach the EST public welome server.
Some HW platforms requires a specific logging implementation. This library doesn't provided any default one, instead offers some macros to be implemented using platform-specific code. The default implementation is a no-ops impl.
The src/lib/include/config.h header file contains
#ifdef EST_CONFIG_CUSTOM_FILE
#include EST_CONFIG_CUSTOM_FILE
#endif
During CMake build you can define this macro specifing a header file that redefines the logging functions. For exampke, if you call cmake with
cmake ... -DEST_CONFIG_CUSTOM_FILE=mylog.h
the file must contains
#include "logger.h"
#undef LOG_INFO
#define LOG_INFO(m) log_info m;
#undef LOG_DEBUG
#define LOG_DEBUG(m) log_debug m;
#undef LOG_WARN
#define LOG_WARN(m) log_warn m;
#undef LOG_ERROR
#define LOG_ERROR(m) log_error m;
where log_xxx are platform specific logging functions implemented and linked in your code.
Same as for logging, you can use the macro
cmake ... -DEST_CONFIG_CUSTOM_FILE=mylog.h
you can undefine and redefine all EST runtime parameters, adapting them to you specific HW or environment. For example
#undef HTTP_RESP_CHUNK_LEN
#define HTTP_RESP_CHUNK_LEN 10000
changes the default value of the HTTP download payload from the default to 10KB.
If you want to submit a fix or a new backend implementation feel free to provide the pull request. Any contribution is welcome :)
Please open a github issue for any question.
The list of RFC requirements.
Level RFC Status
MUST Verifying the EST server's HTTPS URI against IMPLEMENTED the EST server's certificate using Implicit TAs (similar to a common HTTPS exchange).
MUST The client MUST NOT respond to the server's HTTP IMPLEMENTED authentication request unless the client has authorized the EST server.
MUST Certificate validation MUST be performed as per IMPLEMENTED [RFC5280]. The EST server certificate MUST conform to the [RFC5280] certificate profile.
OPTIONAL The client can leverage the binding of a shared NOT IMPLEMENTED credential to a specific EST server with a certificate-less TLS cipher suite.
OPTIONAL TLS with a previously issued client certificate IMPLEMENTED (e.g., an existing certificate issued by the EST CA).
OPTIONAL TLS with a previously installed certificate IMPLEMENTED (e.g., manufacturer-installed certificate or a certificate issued by some other party).
? Certificate-less TLS (e.g., with a shared NOT IMPLEMENTED credential distributed out-of-band);
MUST HTTP-based with a username/password distributed IMPLEMENTED out-of-band.
OPTIONAL A client MAY set the username to the IMPLEMENTED empty string ("""") if it is presenting a password that is not associated with a username.
OPTIONAL The client is expected to retry the request, NOT IMPLEMENTED including the appropriate Authorization Request header ([RFC2617], Section 3.2.2), if the client is capable of using the Basic or Digest authentication.
MUST The client MUST wait at least the specified NOT IMPLEMENTED "retry-after" time before repeating the same request. The client repeats the initial enrollment request after the appropriate "retry-after" interval has expired
MUST EST clients request a certificate from the EST IMPLEMENTED server with an HTTPS POST using the operation path value of "/simpleenroll"
MUST EST clients request a renew/rekey of existing IMPLEMENTED certificates with an HTTP POST using the operation path value of "/simplereenroll"
MUST The client MUST also be able to request CA IMPLEMENTED certificates from the EST server and parse the returned ""bag"" of certificates using /cacerts.
MUST The EST client uses the /cacerts response to IMPLEMENTED establish an Explicit Trust Anchor database for subsequent TLS authentication of the EST server.
MUST EST clients MUST NOT engage in any other protocol IMPLEMENTED exchange until after the /cacerts response has been accepted and a new TLS session has been established (using TLS certificate-based authentication)
OPTIONAL Clients SHOULD request an up-to-date response NOT IMPLEMENTED before stored information has expired in order to ensure the EST CA TA database is up to date.
MUST If the client disables the Implicit TA database NOT IMPLEMENTED and if the EST server certificate was verified using an Implicit TA database entry then the client MUST include the "Trusted CA Indication" extension in future TLS sessions [RFC6066].
MUST The EST server SHOULD include the three NOT IMPLEMENTED "Root CA Key Update" certificates OldWithOld, OldWithNew, and NewWithOld in the response chain. The EST client MUST be able to handle these certificates in the response.
OPTIONAL Implementations conforming to this standard MUST IMPLEMENTED provide the ability to designate Explicit Tas.
MUST After out-of-band validation occurs, all the other IMPLEMENTED certificates MUST be validated using normal [RFC5280] certificate path validation (using the most recent CA certificate as the TA) before they can be used to build certificate paths during certificate validation.
OPTIONAL For human usability reasons, a "fingerprint" of an NOT IMPLEMENTED Explicit TA database entry can be configured for bootstrapping as discussed in Section 4.1.1.
MUST Implementations conforming to this standard MUST IMPLEMENTED provide the ability to disable use of any Implicit TA database.
MUST The client MUST maintain a distinction between the IMPLEMENTED use of Explicit and Implicit TA databases during authentication in order to support proper authorization.
OPTIONAL The client MAY provisionally continue the TLS NOT IMPLEMENTED handshake to completion for the purposes of accessing the /cacerts or /fullcmc method.
OPTIONAL If the EST client continues with an unauthenticated NOT IMPLEMENTED connection, the client MUST extract the HTTP content data from the response (Sections 4.1.3 or 4.3.2) and engage a human user to authorize the CA certificate using out-of-band data such as a CA certificate "fingerprint" (e.g., a SHA-256 or SHA-512 [SHS] hash on the whole CA certificate).
OPTIONAL The EST client can be configured with a tuple IMPLEMENTED composed of the authority portion of the URI along with the OPTIONAL label (e.g., "www.example.com:80" and "arbitraryLabel1")
OPTIONAL HTTP redirections (3xx status codes) to the same NOT IMPLEMENTED web origin (see [RFC6454]) SHOULD be handled by the client without user input so long as all applicable security checks.
MUST HTTPS MUST be used. TLS 1.1 [RFC4346] (or a later IMPLEMENTED version) MUST be used for all EST communications.
OPTIONAL TLS session resumption [RFC5077] SHOULD be supported NOT IMPLEMENTED When performing renegotiation, TLS ""secure_renegotiation"" RFC5746 MUST be used"
OPTIONAL The client can determine if the server requires MOT IMPLEMENTED the linking of identity and POP by examining the CSR Attributes Response.
OPTIONAL Regardless of the CSR Attributes Response, clients IMPLEMENTED SHOULD link identity and POP by embedding tls-unique information in the certification request.
MUST RFC-8951 This document updates [RFC7030] to require IMPLEMENTED the POST request and payload response of all endpoints using base64 encoding, as specified in Section 4 of [RFC4648]. In both cases, the Distinguished Encoding Rules (DER) [X.690] are used to produce the input for the base64 encoding routine. This format is to be used regardless of any Content-Transfer-Encoding header, and any value in such a header MUST be ignored.