Skip to content

RFC 7030 (EST - Enrollment over Secure Transport) SSL pluggable client implementation.

License

Notifications You must be signed in to change notification settings

lgtti/rfc7030-est-client

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

40 Commits
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

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.


Summary
-------
1. Why another EST Client
2. EST Endpoints
3. Build
    3.1. Linux/MacOS
    3.2. Windows
4. Supported Backends
5. Custom TLS/X.509 Backend
    5.1. Function map
    5.2. Example
6. Usage
    6.1. Client
        6.1.1 Example
    6.2. Library
        6.2.1 With CMake
        6.2.2 Without CMake
7. Tests
8. Logging
9. Custom parameters
10. Contribution
11. RFC Requirements



1. Why another EST Client
-------------------------
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.


2. EST Endpoints
----------------
    /cacerts            IMPLEMENTED
    /simpleenroll       IMPLEMENTED
    /simplereenroll     IMPLEMENTED
    /fullcmc            NOT IMPLEMENTED
    /csrattrs           NOT IMPLEMENTED


3. Build
--------
Compile Dependencies:
- picohttpparser
- munit (test only)
- cargs (cli client only)

** Note: all dependencies are downloaded automatically using git submodules.

Current cmake build configuration provides some default arguments you can on/off 
as you wish:
- BUILD_CLONE_SUBMODULES=ON             set to off to avoid close third parts compile 
                                        dependencies.
- USE_OPENSSL=ON                        current default TLS/X.509 backend implementation.
- USE_OPENSSL_CUSTOM_ROOT=OFF           enable the variable USE_OPENSSL_CUSTOM_ROOT_PATH
- USE_OPENSSL_CUSTOM_ROOT_PATH=""       enabled using USE_OPENSSL_CUSTOM_ROOT=ON, 
                                        sets the path used to find the openssl root dir.
- USE_OPENSSL_MANUAL_LINK=OFF           enable manual link to openssl implementation (skip find_package)
- USE_OPENSSL_MANUAL_LINK_INC=""        if manual link is ON, set the openssl include directory
- USE_OPENSSL_MANUAL_LINK_LIB=""        if manual link is ON, set the openssl lib path (you need to set 
                                        at least two libs, libssl and libcrypto). To setup multiple 
                                        libraries use cmake list format eg. 
                                        USE_OPENSSL_MANUAL_LINK_LIB=/path/libssl.so\;/path/libcrypto.so

3.1. Linux/MacOS
----------------
- 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


4. Supported Backends
---------------------
Here the table of native supported TLS/X.509 backends.

| Name              | Folder            | Version   |
|-------------------|-------------------|-----------|
| OpenSSL           | src/openssl       | >= 1.x    |


5. Custom TLS/X.509 Backend
---------------------------
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


5.1. Function map
-----------------
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:
- ESTTLSInterface_t:    used to invoke TLS specific functions, such as init TLS channel and read/write bytes.
- ESTX509Interface_t:   used to parse, decode and encode specific X.509 objects such as 
                        Certificates, Store, PKCS7 formats.

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.


5.2. Example
------------
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:
        - rfc7030_init
        - rfc7030_get_config
        - rfc7030_request_cachain
        - rfc7030_request_certificate
        - rfc7030_renew_certificate

- 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


6. Usage
--------
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.


6.1. Client
-----------
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.


6.1.1 Example
-------------
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.


6.2. Library
------------
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 uswe the low level EST library
functions.

6.2.1 With CMake
------------
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


6.2.2 Without CMake
-------------------
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

- 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

To link the selected backend you need to do the same.


7. Tests
--------
- Run unit tests:
    
    ./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.


8. Logging
----------
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.


9. Custom parameters
--------------------
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.

10. Contribution
---------------
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.

11. RFC Requirements
-------------------
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.