End-to-end Symmetric KMS

Service overview

PSK (Pre-Shared Key) cipher suites are ideal for embedded systems that have very limited computing power and only talk to a very small number of servers. With PSK, each side of the connection already has an agreed upon key to use during the TLS handshake. This reduces resource consumption for each session.

E2E Symmetric KMS (Key Management System) is a highly scalable method for provisioning and managing session unique PSKs for application layer security. A PSK and a PSKIdentity are generated by the RoT within the module, and used to secure end-to-end communications (e.g. via DTLS) to a customer’s cloud service. In particular, during (D)TLS handshake, the module sends the PSKIdentity generated by the RoT inside the ClientKeyExchange message. Once the customer’s cloud service gets this information, it will send the PSKIdentity to the u-blox Thingstream platform (via a REST API) in order to retrieve the same PSK that was used by the module to encrypt the end-to-end communications. The u-blox Thingstream platform uses the PSKIdentity to re-generate the PSK, without having to communicate with the module.

This delivers the following advantages by:

Customers have the option of either:


In this section

Related Information

Security Services API documentation

Tools and Software

GitHub repository

End-to-end Data Protection

Still need help?

If you need more help or have any questions, please send an email to services-support@u-blox.com.


Use cases

Once the device has been bootstrapped and the pre-shared keys (PSK) provisioning functionality has been enabled, this functionality can be called to access the required keys, as described below:

The following AT command can be used to retrieve an identity and PSK value pair for encrypting point-to-point communication:

The module includes a (D)TLS security layer profile manager, which handles security profiles containing (D)TLS connection properties. Each security profile can be associated to sockets or higher level applications (e.g., HTTP, MQTT) using the module internal (D)TLS stack. In general, the AT+USECPRF command is used to configure a security profile.

The following AT commands can be used to configure a security profile on the module with certain PSKIdentity and PSK:

This way, associating a TCP socket to security profile 0, PSKIdentity and PSK will be used to handle the TLS communication through that TCP socket.

Examples

Following are some examples of the procedure described above.

These are example commands and do not use real world API keys or authorization headers. Actual API secret key and authorization headers must first be created before running these commands.

AT+USECPSK=16


+USECPSK: "11010008002F33244B115B0AEEB9","E5DE45B367DB690F2E17CF9D80A18E87"

OK

This step depends on the (D)TLS stack used. We provide 2 examples:

openssl s_client -psk_identity "11010008002F33244B115B0AEEB9" -psk "E5DE45B367DB690F2E17CF9D80A18E87" -connect <server_IP:server_port>

Configure a security profile (profile 0 in this example):

AT+USECPRF=0,8,"E5DE45B367DB690F2E17CF9D80A18E87",1

OK

AT+USECPRF=0,9,"11010008002F33244B115B0AEEB9"

OK

Then, create a socket and enable the secure option on the socket, associating the security profile 0 to it:

AT+USOCR=6

+USOCR: 0              <-- created socket with id 0

OK

AT+USOSEC=0,1,0        <-- associate socket 0 to security profile 0

OK

Connect the socket to the remote service:

AT+USOCO=0,"<server_IP>",<server_port>

The actual way to extract the PSKIdentity from the ClientKeyExchange message can vary and depends on the (D)TLS stack used.

For example, a server application using OpenSSL libraries and wishing to use PSKs for TLSv1.2 and below, must provide a callback function called when the server receives the ClientKeyExchange message. This function has the purpose of fetching the correct PSK starting from the PSKIdentity retrieved from the client. The callback function is set by calling SSL_CTX_set_psk_server_callback(SSL_CTX *ctx, SSL_psk_server_cb_func cb):

#include <openssl/ssl.h>

#include <openssl/err.h>

SSL_CTX *ctx;

const SSL_METHOD *method;

 

method = SSLv23_server_method();

ctx = SSL_CTX_new(method);

if (!ctx) {

    ERR_print_errors_fp(stderr);

    return -1;

}

SSL_CTX_set_ecdh_auto(ctx, 1);

SSL_CTX_use_psk_identity_hint(ctx, "hint hint");

SSL_CTX_set_psk_server_callback(ctx, psk_server_cb);

During (D)TLS handshake, when the server receives the ClientKeyExchange message, the psk_server_cb function is called.

static unsigned int psk_server_cb(SSL *ssl,

                const char *identity,

                unsigned char *psk,

                unsigned int max_psk_len) {

    char* py_psk;

    if (identity == NULL) {

        return 0;

    }

    /* Retrieve the PSK for the given identity */

/* … */

 

See OpenSSL documentation for more details (https://www.openssl.org/docs/).

Once the PSKIdentity is retrieved, the customer can obtain the PSK via the GetPSK REST API call (https://ssapi.services.u-blox.com/v1/GetPSK). Make sure to have an AuthToken to use for the Authorization header – if not, call the Authorize API to get one.

We show the API call using cURL: we have to specify the PSKIdentity in the KeyID parameter and, optionally, the PSK length (in bits) in the KeyLength parameter:

curl -X POST "https://ssapi.services.u-blox.com/v1/GetPSK" -H "accept: application/json" -H "Authorization: [AuthToken]" -H "Content-Type: application/json" -d "{ \"KeyID\": \"11010008002F33244B115B0AEEB9\", \"KeyLength\": \"128\"}"

In the previous C server application, it’s possible for example to use the libcurl library to perform the API request. See libcurl documentation for more details (https://curl.haxx.se/libcurl/c/).

{

    "Key": "5d5Fs2fbaQ8uF8+dgKGOhw==",

    "ROTPublicUID": "0002000089282245"

}

SSL *ssl;

const SSL_METHOD *method;

method = SSLv23_server_method();

 

SSL_CTX_set_ecdh_auto(ctx, 1);

SSL_CTX_use_psk_identity_hint(ctx, "hint hint");

SSL_CTX_set_psk_server_callback(ctx, psk_server_cb);

 

ssl = SSL_new(ctx);

if (ssl == NULL) {

    // Failed to initialise SSL buffer

    return NULL;

}

if (0 == SSL_set_fd(ssl, sock_fd)) {

// Failed to configure IO for the SSL socket

    ERR_print_errors_fp(stderr);

    return NULL;

};

 

if (SSL_accept(ssl) <= 0) {

// Failed to setup SSL socket as server

    ERR_print_errors_fp(stderr);

    SSL_free(ssl);

    return NULL;

}

At this point, the server application can exchange data through the secure socket by using SSL_read() and SSL_write. See OpenSSL documentation for more details (https://www.openssl.org/docs/).

Availability

The End-to-end Symmetric Key Management System is available from the following FW version an subsequent releases: