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:

  • Achieving up to eight times reduction in the secure communication data overhead, and therefore reducing cost for data consumption when compared with PKI-based TLS.

  • Simplifying both the development and the actual process of obtaining the key by delegating the key management to the u-blox solution.

Customers have the option of either:

  • Using their own communication stack: in this scenario, the customer requests a PSK and PSKIdentity pair from the module and uses it to establish a PSK based communication with its own (D)TLS stack.

  • Using the communication stacks provided by u-blox module: in this scenario the module is configured to automatically establish a PSK based secure connection when trying to connect to a (D)TLS endpoint using any Internet protocol based application provided by the module.

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 support@thingstream.io.

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:

  1. The customer’s application running on the device makes a request to the u-blox module and retrieves a PSK and PSKIdentity pair from the RoT by using the AT+USECPSK command.

  2. The customer configures their own (D)TLS stack to use the PSK and PSKIdentity that are retrieved to secure the communication with its endpoint.

  3. The PSKIdentity is sent during the (D)TLS handshake as the “Identity” element of the ClientKeyExchange message, and the PSK is used to encrypt/decrypt the (D)TLS session data.

  4. The customer’s remote service extracts the PSKIdentity from the ClientKeyExchange message and forwards it to the u-blox security service via the GetPSK API.

  5. The information received by the u-blox security service is used to:

    1. Validate the customer

    2. Validate the device making the request is assigned to this customer account

    3. Confirm that PSK provisioning is enabled on this device

  6. If all the actions in item 5 are true, i.e. the request is valid, then the u-blox security service passes the PSK back to the customer’s remote service in the GetPSK API response.

  7. The customer’s remote service can now use the received PSK to establish the (D)TLS session.

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.


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.

  • Get PSK and PSKIdentity from RoT. For example, get a 16 bytes long PSK:


+USECPSK: "11010008002F33244B115B0AEEB9","E5DE45B367DB690F2E17CF9D80A18E87"


  • 11010008002F33244B115B0AEEB9 is the PSKIdentity in hex format: this has to be sent to the remote service during the (D)TLS handshake.

  • E5DE45B367DB690F2E17CF9D80A18E87 is the actual PSK in hex format: this can be used to encrypt the communication to the remote service.

  • Configure the (D)TLS stack to use the PSKIdentity and PSK generated by RoT.

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

  • Use OpenSSL command to test the connection to the remote service.

    • Call OpenSSL this way:

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

    • Use a modem internal socket to communicate to the remote service.

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





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


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


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


Connect the socket to the remote service:


  • Analyzing the communication between client and remote service, we can see the PSKIdentity being sent by the client in the ClientKeyExchange message during (D)TLS handshake:

  • On the server side.

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) {


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/).

  • The API returns a JSON containing the PSK encoded using base64:


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

"ROTPublicUID": "0002000089282245"


  • Considering the C server application from above, at this point the server can create a server socket (sock_fd) and wrap it with the OpenSSL context from before (ctx):

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


return NULL;


if (SSL_accept(ssl) <= 0) {

// Failed to setup SSL socket as server



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/).


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

  • SARA-R410M-x3B-01 (x3B = 63B, 73B, 83B)

  • SARA-R422S-00B-00, SARA-R422M8S-00B-00

  • SARA-R500S-00B-00, SARA-R510S-00B-00, SARA-R510M8S-00B-00

  • SARA-R500S-01B-00, SARA-R510S-01B-00, SARA-R510M8S-01B-00

  • ALEX-R510M8S-01B-00

  • LARA-R6 series