Connecting to your own MQTT/TLS server

The following paragraphs describe how to connect the SpringCore device to a Mosquitto MQTT broker, using only ECC key, predefined SpringCard-supplied certificate 0D or your own certificates.

Please refer to the free SpringCard SDK for SpringCore+MQTT (available on GitHub) for details: https://github.com/springcard/springcard.springcore-mqtt.sdk (WARNING: PRELIMINARY INFORMATION - SERVICE IS NOT YET AVAILABLE).

Principles

The aim of this tutorial is to set up a Mosquitto broker and to configure the SpringCore device accordingly.

First we will not use any encryption, in a second time we will use a certificate only on the server side then we will also use encryption on the client side using default certificates of the device and last, we will generate client's certificate and pout them into the device.

Here is the list of the referece that will be useful:

Overview of Steps

  1. Use a local broker without encryption
    1. Install the mosquitto broker
    2. Test the broker with mosquitto clients
    3. Configure the device
    4. Test the connection between the device and the broker

  1. Use a certificate on the broker's side
    1. Create a CA key
    2. Create CA certificate and use the CA key from step 1 to sign it
    3. Create a broker key
    4. Create a broker certificate request using key from step 3
    5. Use the CA certificate to sign the broker certificate request from step 4
    6. Now we should have a CA key file,a CA certificate file, a broker key file, and a broker certificate file
    7. Place all files in a directory on the broker
    8. Edit the broker configuration
    9. Test the connection with the broker with mosquitto-clients
    10. Configure the device with the CA and activate TLS
    11. Test the connection between the device and the broker

  1. Use TLS on the server's side and the client's side (with its default key and certificate)
    1. Copy the SpringCore device CA certificate on the broker
    2. Edit the broker configuration
    3. Configure the device to use default certificate and key
    4. Test the connection between the device and the broker

  1. Use TLS on the broker and the client's side with your own certificates
    1. Edit the broker configuration
    2. Create a client key
    3. Create a client certificate request using the key
    4. Use the CA key to sign the client certificate request from step 3
    5. Configure the device with the key and certificate of the previous steps
    6. Test the connection between the device and the broker

Use a local broker without encryption

As previously indicated, the first step is to install the mosquitto broker.

Mosquitto is widely available on on all major Linux distributions, so the first step is to install this packages and some other utilities.

On Debian/Ubuntu-based distributions:

$ sudo apt install mosquitto mosquitto-clients openssl

Verify that it is running, otherwise you can start it with one of theses commands

$ sudo systemctl start mosquitto.service
$ sudo mosquitto -c /etc/mosquitto/mosquitto.conf -v

For indication you can use the following configuration file:

log_type all
log_dest stdout
log_dest file /var/log/mosquitto/mosquitto.log
per_listener_settings true


listener 1883
allow_anonymous true

The path of this file is /etc/mosquitto/mosquitto.conf.

...
2021-04-09T10:52:36: mosquitto version 2.0.7 running
2021-04-09T10:52:45: New connection from 192.168.1.13:63224 on port 1883.
2021-04-09T10:52:45: New client connected from 192.168.1.13:63224 as 000000000003 (p2, c1, k10).
2021-04-09T10:52:45: Will message specified (24 bytes) (r1, q0).
2021-04-09T10:52:45:    springcard/springcore/000000000003/status
2021-04-09T10:52:45: Sending CONNACK to 000000000003 (0, 0)
2021-04-09T10:52:45: Received SUBSCRIBE from 000000000003
2021-04-09T10:52:45:    springcard/springcore/000000000003/host (QoS 1)
2021-04-09T10:52:45: 000000000003 1 springcard/springcore/000000000003/host
2021-04-09T10:52:45:    springcard/springcore/000000000003 (QoS 1)
2021-04-09T10:52:45: 000000000003 1 springcard/springcore/000000000003
2021-04-09T10:52:45:    springcard/springcore/000000000003/rdr/cmd (QoS 1)
2021-04-09T10:52:45: 000000000003 1 springcard/springcore/000000000003/rdr/cmd
2021-04-09T10:52:45: Sending SUBACK to 000000000003
2021-04-09T10:52:45: Received PUBLISH from 000000000003 (d0, q1, r1, m3, 'springcard/springcore/000000000003/meta', ... (231 bytes))
2021-04-09T10:52:45: Sending PUBACK to 000000000003 (m3, rc0)
2021-04-09T10:52:45: Received PUBLISH from 000000000003 (d0, q1, r1, m5, 'springcard/springcore/000000000003/status', ... (45 bytes))
2021-04-09T10:52:45: Sending PUBACK to 000000000003 (m5, rc0)
...

It is important to note that some MQTT clients will need a real name instead of the IP address to connect to a MQTTS server.

It is strongly advised to put your machine name or FQDN as Common Name of your server certifcate. If you want to test in a local network only, just can update the files /etc/hosts, /etc/hostname or your local DNS resolver. The easiest alternative is to disable SNI and Server CN verification.

In this tutorial, the MQTT broker we will use as example will be denominated 'mqtt_demo', but you can use your own domain or IP address.

Now we can connect to it with mosquitto-clients:

$ mosquitto_pub -h mqtt_demo -t "test" -m "test" -d
Client (null) sending CONNECT
Client (null) received CONNACK (0)
Client (null) sending PUBLISH (d0, q0, r0, m1, 'test', ... (4 bytes))
Client (null) sending DISCONNECT

Now, to configure the the springpark you can use the file springcore-mqtt-local-no-tls.json

If you have the SpringCore Tools installed, just run the command

> SpringCoreConfig --url https://docs.springcard.com/books/SpringCore/Appendixes/PKI_keys_and_certificates/TLS_client_with_default_certificate/springcore-mqtt-local-1-no-tls.json

(you may have to specifiy how the software shall connect to the SpringCore device at the end of the command-line).

The content of the file is as follow:

{
	"type": "multiconf-v2",
	"config" : {
		"80": "",
		"86.string" : "mqtt_demo",
		"87" : "",
		"88" : "",
		"89" : "5514030A1E1E",
		"8B" : "",
		"8C" : "",
		"8D" : "",
		"8E" : "",
		"8F" : "",
		"C0" : "64"
	}
}
Register Content
0280 IPv4 Settings IPv4 parameters (address, mask, gateway, DNS servers)
Leave empty for DHCP operation
0286 MQTT : Server Hostname of MQTT server:
"mqtt_demo" or the IP address of your broker
0287 MQTT : Port Listen port of the MQTT server
Leave empty for default value 1883 if TLS is not used
0288 MQTT : TLS Options Leave empty for this use case
0289 MQTT : Client Options Use the following settings:
- QoS used for subscribing: 1
- QoS used for publishing: 1
- Don't create topic before subscribe
- Disable Last Will Message
- Disable Retained Messages
- Connection timeout: 30s
- Response timeout: 3s
- Keep alive interval: 10s
- Status publish interval: 30s
- Reconnect interval: 30s

The value to put in the register is therefore 5014030A1E1E
028B MQTT : Login Must be empty
028C MQTT : Password Must be empty
028D MQTT : Client ID Leave empty. Doing so, the device uses its Serial Number as Client ID.
028E MQTT : Topic prefix Leave empty. Doing so, the device's topics are under "springcard/springcore".
028F MQTT : Device ID Leave empty. Doing so, the device uses its Serial Number as Device ID.
02C0 Main configuration : Profile Set to 64 for Smart Reader operation through MQTT client

Once configured the device will reset and try to connect to the broker.

You can verify that the device is connected by checking the logs or by subscribing to the "#" topic.

...
2021-04-09T10:52:45: New connection from 192.168.1.13:63224 on port 1883.
2021-04-09T10:52:45: New client connected from 192.168.1.13:63224 as 000000000003 (p2, c1, k10).
2021-04-09T10:52:45: Will message specified (24 bytes) (r1, q0).
2021-04-09T10:52:45:    springcard/springcore/000000000003/status
2021-04-09T10:52:45: Sending CONNACK to 000000000003 (0, 0)
2021-04-09T10:52:45: Received SUBSCRIBE from 000000000003
2021-04-09T10:52:45:    springcard/springcore/000000000003/host (QoS 1)
2021-04-09T10:52:45: 000000000003 1 springcard/springcore/000000000003/host
2021-04-09T10:52:45:    springcard/springcore/000000000003 (QoS 1)
2021-04-09T10:52:45: 000000000003 1 springcard/springcore/000000000003
2021-04-09T10:52:45:    springcard/springcore/000000000003/rdr/cmd (QoS 1)
2021-04-09T10:52:45: 000000000003 1 springcard/springcore/000000000003/rdr/cmd
2021-04-09T10:52:45: Sending SUBACK to 000000000003
2021-04-09T10:52:45: Received PUBLISH from 000000000003 (d0, q1, r1, m3, 'springcard/springcore/000000000003/meta', ... (231 bytes))
2021-04-09T10:52:45: Sending PUBACK to 000000000003 (m3, rc0)
2021-04-09T10:52:45: Received PUBLISH from 000000000003 (d0, q1, r1, m5, 'springcard/springcore/000000000003/status', ... (45 bytes))
2021-04-09T10:52:45: Sending PUBACK to 000000000003 (m5, rc0)
...
$ mosquitto_sub -h mqtt_demo -t "#" -v
springcard/springcore/000000000003/meta {"VendorName":"SpringCard","ProductName":"SpringPark","Hardware":"","Firmware":"springcore/e518/springpark","Version":"1.20","SerialNumber":"000000000003","PhysAddress":"7490500079FF","IpAddress":"192.168.1.13","Protocol":"$SCRDR"}
springcard/springcore/000000000003/status {"State":"online,ready","Uptime":"130:325.279"}
springcard/springcore/000000000003/rdr/evt {"Interface":"13.56","Protocol":"NFC-A","Template":1,"TagId":"04A17B02C84080","TagData":"0004A17B02C84080","Uptime":"130:345.183"}
...

Use a certificate on the broker's side

The second step is to use TLS with a certificate on the server's side, verified by putting the CA certificate in the cliient's side.

To do so we will have to generate the keys and certificates of the self-signed CA and server.

Note: At the moment the SpringCore devices only support ECC keys.

First create a key for the CA

$ openssl ecparam -genkey -name prime256v1 -noout -out ca.key

Now Create a certificate for the CA using the CA key

$ openssl req -new -x509 -days 1826 -key ca.key -out ca.crt
You are about to be asked to enter information that will be incorporated
into your certificate request.
What you are about to enter is what is called a Distinguished Name or a DN.
There are quite a few fields but you can leave some blank
For some fields there will be a default value,
If you enter '.', the field will be left blank.
-----
Country Name (2 letter code) [AU]:
State or Province Name (full name) [Some-State]:
Locality Name (eg, city) []:
Organization Name (eg, company) [Internet Widgits Pty Ltd]:
Organizational Unit Name (eg, section) []:BE
Common Name (e.g. server FQDN or YOUR name) []:MQTT_DEMO CA
Email Address []:

Now we create a server key that will be used by the broker

$ openssl ecparam -genkey -name prime256v1 -noout -out server.key

Now we create a certificate request .csr. When filling out the form the common name is important and is usually the domain name of the server.

You should use the Full domain name. You must use the same name when configuring the client connection.

$ openssl req -new -out server.csr -key server.key
You are about to be asked to enter information that will be incorporated
into your certificate request.
What you are about to enter is what is called a Distinguished Name or a DN.
There are quite a few fields but you can leave some blank
For some fields there will be a default value,
If you enter '.', the field will be left blank.
-----
Country Name (2 letter code) [AU]:
State or Province Name (full name) [Some-State]:
Locality Name (eg, city) []:
Organization Name (eg, company) [Internet Widgits Pty Ltd]:
Organizational Unit Name (eg, section) []:BE
Common Name (e.g. server FQDN or YOUR name) []:mqtt_demo
Email Address []:

Please enter the following 'extra' attributes
to be sent with your certificate request
A challenge password []:
An optional company name []:

Now we use the CA key to verify and sign the server certificate. This creates the server.crt file

$ openssl x509 -req -in server.csr -CA ca.crt -CAkey ca.key -CAcreateserial -out server.crt -days 360
Signature ok
subject=C = AU, ST = Some-State, O = Internet Widgits Pty Ltd, OU = BE, CN = mqtt_demo
Getting CA Private Key

Copy the ca.crt file in the directory /etc/mosquitto/ca_certificates

$ sudo cp ca.crt /etc/mosquitto/ca_certificates

Copy the server.crt and server.key files in the directory /etc/mosquitto/certs

$ sudo cp server.crt server.key /etc/mosquitto/certs

Do not forget to copy the ca.crt on the client, it will be used to verify the server's certificate.

Edit the mosquitto configuration to look like this:

log_type all
log_dest stdout
log_dest file /var/log/mosquitto/mosquitto.log
per_listener_settings true


listener 8883
allow_anonymous true
cafile /etc/mosquitto/ca_certificates/ca.crt
certfile /etc/mosquitto/certs/server.crt
keyfile /etc/mosquitto/certs/server.key

Now launch mosquitto and try to publish in a topic with mosquitto_pub with the CA specified to verify the server certificate.

$ mosquitto_pub -h mqtt_demo -p 8883 -t "test" -m "test" --cafile ca.crt -d -i "TEST-CLIENT"
Client TEST-CLIENT sending CONNECT
Client TEST-CLIENT received CONNACK (0)
Client TEST-CLIENT sending PUBLISH (d0, q0, r0, m1, 'test', ... (4 bytes))
Client TEST-CLIENT sending DISCONNECT

In the logs we can see the client connecting on port 8883

...
2021-04-09T11:33:43: New connection from 192.168.1.142:63128 on port 8883.
2021-04-09T11:33:43: New client connected from 192.168.1.142:63128 as TEST-CLIENT (p2, c1, k60).
2021-04-09T11:33:43: No will message specified.
2021-04-09T11:33:43: Sending CONNACK to TEST-CLIENT (0, 0)
2021-04-09T11:33:43: Received PUBLISH from TEST-CLIENT (d0, q0, r0, m0, 'test', ... (4 bytes))
2021-04-09T11:33:43: Received DISCONNECT from TEST-CLIENT
2021-04-09T11:33:43: Client TEST-CLIENT disconnected.
...

It is now time to configure our device.

We will need to load the certificate of the CA in the device to make possible the verification of the server.

The command below can be used to reatrieve the base64 payload of a PEM encoded certificate without newline charatcters and header/footer:

$ cat ca.crt | sed '1d;$d' | tr -d '\n'  | awk '{print $1}'
MIICJjCCAc2gAwIBAgIUNPqK5VyOX1X2EiIGnXSYVEGJk4MwCgYIKoZIzj0EAwIwaTELMAkGA1UEBhMCQVUxEzARBgNVBAgMClNvbWUtU3RhdGUxITAfBgNVBAoMGEludGVybmV0IFdpZGdpdHMgUHR5IEx0ZDELMAkGA1UECwwCQkUxFTATBgNVBAMMDE1RVFRfREVNTyBDQTAeFw0yMTA0MDkxMDA5MDFaFw0yNjA0MDkxMDA5MDFaMGkxCzAJBgNVBAYTAkFVMRMwEQYDVQQIDApTb21lLVN0YXRlMSEwHwYDVQQKDBhJbnRlcm5ldCBXaWRnaXRzIFB0eSBMdGQxCzAJBgNVBAsMAkJFMRUwEwYDVQQDDAxNUVRUX0RFTU8gQ0EwWTATBgcqhkjOPQIBBggqhkjOPQMBBwNCAAQOMlwL4Y8FUlqSJacXUR8cXleCFps3XXDKyGuTm2i26S4aoGP0NQ6P75KRU3sPuqYcQR4hvZ+ZhtBR2ptVlZ4zo1MwUTAdBgNVHQ4EFgQUKzhMLyefO1ME9FkoAx/mYPBPYAgwHwYDVR0jBBgwFoAUKzhMLyefO1ME9FkoAx/mYPBPYAgwDwYDVR0TAQH/BAUwAwEB/zAKBggqhkjOPQQDAgNHADBEAiB4aWr0S1TIpK5eja+xgQeT5XDtrH3ZJa3UqApT74JqYQIgXic1IcCTaTWEeEI2hrC1OKHRdS0VB56t1FqauQXY/lI=

Once the base64 obtained, it can be put into the json configuration file.

{
	"type": "multiconf-v2",
	"config" : {
		"80": "",
		"86.string" : "192.168.0.10",
		"87" : "",
		"88" : "2102000000",
		"89" : "5514030A1E1E",
		"8B" : "",
		"8C" : "",
		"8D" : "",
		"8E" : "",
		"8F" : "",
		"C0" : "64"
	},
	"certificates" : {	
		"02.base64" : "MIICJjCCAc2gAwIBAgIUNPqK5VyOX1X2EiIGnXSYVEGJk4MwCgYIKoZIzj0EAwIwaTELMAkGA1UEBhMCQVUxEzARBgNVBAgMClNvbWUtU3RhdGUxITAfBgNVBAoMGEludGVybmV0IFdpZGdpdHMgUHR5IEx0ZDELMAkGA1UECwwCQkUxFTATBgNVBAMMDE1RVFRfREVNTyBDQTAeFw0yMTA0MDkxMDA5MDFaFw0yNjA0MDkxMDA5MDFaMGkxCzAJBgNVBAYTAkFVMRMwEQYDVQQIDApTb21lLVN0YXRlMSEwHwYDVQQKDBhJbnRlcm5ldCBXaWRnaXRzIFB0eSBMdGQxCzAJBgNVBAsMAkJFMRUwEwYDVQQDDAxNUVRUX0RFTU8gQ0EwWTATBgcqhkjOPQIBBggqhkjOPQMBBwNCAAQOMlwL4Y8FUlqSJacXUR8cXleCFps3XXDKyGuTm2i26S4aoGP0NQ6P75KRU3sPuqYcQR4hvZ+ZhtBR2ptVlZ4zo1MwUTAdBgNVHQ4EFgQUKzhMLyefO1ME9FkoAx/mYPBPYAgwHwYDVR0jBBgwFoAUKzhMLyefO1ME9FkoAx/mYPBPYAgwDwYDVR0TAQH/BAUwAwEB/zAKBggqhkjOPQQDAgNHADBEAiB4aWr0S1TIpK5eja+xgQeT5XDtrH3ZJa3UqApT74JqYQIgXic1IcCTaTWEeEI2hrC1OKHRdS0VB56t1FqauQXY/lI="
	}
}

The other register to look at is the 88 (TLS Options).

Register Content
0280 IPv4 Settings IPv4 parameters (address, mask, gateway, DNS servers)
Leave empty for DHCP operation
0286 MQTT : Server Hostname of MQTT server:
"mqtt_demo" or the IP address of your broker
0287 MQTT : Port Listen port of the MQTT server
Leave empty for default value 8883 if TLS is used
0288 MQTT : TLS Options Use the following settings:
- TLS enabled
- SNI disabled
- Don't verify CN (Server Name)
- Verify CA (no chaining)
- Verify public key only
- Server CA certificate is in slot 2 (02)
- Disable client authentication

The value to put in the register is therefore 2102000000
0289 MQTT : Client Options Use the following settings:
- QoS used for subscribing: 1
- QoS used for publishing: 1
- Don't create topic before subscribe
- Disable Last Will Message
- Disable Retained Messages
- Connection timeout: 30s
- Response timeout: 3s
- Keep alive interval: 10s
- Status publish interval: 30s
- Reconnect interval: 30s

The value to put in the register is therefore 5014030A1E1E
028B MQTT : Login Must be empty
028C MQTT : Password Must be empty
028D MQTT : Client ID Leave empty. Doing so, the device uses its Serial Number as Client ID.
028E MQTT : Topic prefix Leave empty. Doing so, the device's topics are under "springcard/springcore".
028F MQTT : Device ID Leave empty. Doing so, the device uses its Serial Number as Device ID.
02C0 Main configuration : Profile Set to 64 for Smart Reader operation through MQTT client

Once configured, the device will connect on port 8883 of the broker, as we can see in the logs below:

...
2021-04-09T11:50:43: New connection from 192.168.1.13:63224 on port 8883.
2021-04-09T11:50:48: New client connected from 192.168.1.13:63224 as 000000000003 (p2, c1, k10).
2021-04-09T11:50:48: Will message specified (24 bytes) (r1, q0).
2021-04-09T11:50:48:    springcard/springcore/000000000003/status
2021-04-09T11:50:48: Sending CONNACK to 000000000003 (0, 0)
...

Add TLS on the the client's side (with its default key and certificate)

The first thing to do is to copy the file springcore-client-ca-chained.crt on the server.

This CA certificate is used to verify default client's certifictaes loaded inside the devices.

$ sudo cp springcore-client-ca-chained.crt /etc/mosquitto/ca_certificates

The mosquitto configuration must be edited accordingly to look like this:

log_type all
log_dest stdout
log_dest file /var/log/mosquitto/mosquitto.log
per_listener_settings true


listener 8883
allow_anonymous true
cafile /etc/mosquitto/ca_certificates/springcore-client-ca-chained.crt
certfile /etc/mosquitto/certs/server.crt
keyfile /etc/mosquitto/certs/server.key
require_certificate true

the important lines that have been changed are:

  • cafile /etc/mosquitto/ca_certificates/springcore-client-ca-chained.crt which correspond of the path to the CA used to verify the clients
  • require_certificate true indicates that the client that want to connect to this port must provide a valid cartificate

Now that the broker configuration that have been updated, we can laod this configuration inside the device.

{
	"type": "multiconf-v2",
	"config" : {
		"80": "",
		"86.string" : "mqtt_demo",
		"87" : "",
		"88" : "21028D4D00",
		"89" : "5514030A1E1E",
		"8B" : "",
		"8C" : "",
		"8D" : "",
		"8E" : "",
		"8F" : "",
		"C0" : "64"
	},
	"certificates" : {	
		"02.base64" : "MIICJjCCAc2gAwIBAgIUNPqK5VyOX1X2EiIGnXSYVEGJk4MwCgYIKoZIzj0EAwIwaTELMAkGA1UEBhMCQVUxEzARBgNVBAgMClNvbWUtU3RhdGUxITAfBgNVBAoMGEludGVybmV0IFdpZGdpdHMgUHR5IEx0ZDELMAkGA1UECwwCQkUxFTATBgNVBAMMDE1RVFRfREVNTyBDQTAeFw0yMTA0MDkxMDA5MDFaFw0yNjA0MDkxMDA5MDFaMGkxCzAJBgNVBAYTAkFVMRMwEQYDVQQIDApTb21lLVN0YXRlMSEwHwYDVQQKDBhJbnRlcm5ldCBXaWRnaXRzIFB0eSBMdGQxCzAJBgNVBAsMAkJFMRUwEwYDVQQDDAxNUVRUX0RFTU8gQ0EwWTATBgcqhkjOPQIBBggqhkjOPQMBBwNCAAQOMlwL4Y8FUlqSJacXUR8cXleCFps3XXDKyGuTm2i26S4aoGP0NQ6P75KRU3sPuqYcQR4hvZ+ZhtBR2ptVlZ4zo1MwUTAdBgNVHQ4EFgQUKzhMLyefO1ME9FkoAx/mYPBPYAgwHwYDVR0jBBgwFoAUKzhMLyefO1ME9FkoAx/mYPBPYAgwDwYDVR0TAQH/BAUwAwEB/zAKBggqhkjOPQQDAgNHADBEAiB4aWr0S1TIpK5eja+xgQeT5XDtrH3ZJa3UqApT74JqYQIgXic1IcCTaTWEeEI2hrC1OKHRdS0VB56t1FqauQXY/lI="
	}
}

The only register that have changed is register 88.

Register Content
0280 IPv4 Settings IPv4 parameters (address, mask, gateway, DNS servers)
Leave empty for DHCP operation
0286 MQTT : Server Hostname of MQTT server:
"mqtt_demo" or the IP address of your broker
0287 MQTT : Port Listen port of the MQTT server
Leave empty for default value 8883 if TLS is used
0288 MQTT : TLS Options Use the following settings:
- TLS enabled
- SNI disabled
- Don't verify CN (Server Name)
- Verify server CA certificate
- Verify public key only
- Server certificate is in slot 7 (02)
- Enable client authentication
- Client certificate is in slot 13 (0D)
- Client private key is in ATECC
- Client private key is in slot 13 (0D)
- Don't chain CA certicate with client certificate

The value to put in the register is therefore 21028D4D00
0289 MQTT : Client Options Use the following settings:
- QoS used for subscribing: 1
- QoS used for publishing: 1
- Don't create topic before subscribe
- Disable Last Will Message
- Disable Retained Messages
- Connection timeout: 30s
- Response timeout: 3s
- Keep alive interval: 10s
- Status publish interval: 30s
- Reconnect interval: 30s

The value to put in the register is therefore 5014030A1E1E
028B MQTT : Login Must be empty
028C MQTT : Password Must be empty
028D MQTT : Client ID Leave empty. Doing so, the device uses its Serial Number as Client ID.
028E MQTT : Topic prefix Leave empty. Doing so, the device's topics are under "springcard/springcore".
028F MQTT : Device ID Leave empty. Doing so, the device uses its Serial Number as Device ID.
02C0 Main configuration : Profile Set to 64 for Smart Reader operation through MQTT client

Once configured we can see in the logs of the broker that the device is connected:

...
2021-04-09T13:54:35: New connection from 192.168.1.13:63241 on port 8883.
2021-04-09T13:54:41: New client connected from 192.168.1.13:63241 as 000000000003 (p2, c1, k10).
2021-04-09T13:54:41: Will message specified (24 bytes) (r1, q0).
2021-04-09T13:54:41:    springcard/springcore/000000000003/status
2021-04-09T13:54:41: Sending CONNACK to 000000000003 (0, 0)
2021-04-09T13:54:41: Received SUBSCRIBE from 000000000003
...

Use TLS on the broker and the client's side with your own certificates

Finally, we will see how to use tour own certificates for your client.

To do this we will use the same CA used previously.

The first step of this part is to edit the mosquitto configuration file to set the CA file with the old ca.crt we generated before.

log_type all
log_dest stdout
log_dest file /var/log/mosquitto/mosquitto.log
per_listener_settings true


listener 8883
allow_anonymous true
cafile /etc/mosquitto/ca_certificates/ca.crt
certfile /etc/mosquitto/certs/server.crt
keyfile /etc/mosquitto/certs/server.key
require_certificate true

Now to create a client key.

$ openssl ecparam -genkey -name prime256v1 -noout -out client.key

Next create a certificate request and use the client private key to sign it.

$ openssl req -new -out client.csr -key client.key
You are about to be asked to enter information that will be incorporated
into your certificate request.
What you are about to enter is what is called a Distinguished Name or a DN.
There are quite a few fields but you can leave some blank
For some fields there will be a default value,
If you enter '.', the field will be left blank.
-----
Country Name (2 letter code) [AU]:
State or Province Name (full name) [Some-State]:
Locality Name (eg, city) []:
Organization Name (eg, company) [Internet Widgits Pty Ltd]:
Organizational Unit Name (eg, section) []:
Common Name (e.g. server FQDN or YOUR name) []:TEST-CLIENT-DEMO
Email Address []:

Please enter the following 'extra' attributes
to be sent with your certificate request
A challenge password []:
An optional company name []:

Now we complete the request and create a client certificate. The command is:

$ openssl x509 -req -in client.csr -CA ca.crt -CAkey ca.key -CAcreateserial -out client.crt -days 360
Signature ok
subject=C = AU, ST = Some-State, O = Internet Widgits Pty Ltd, CN = TEST-CLIENT-DEMO
Getting CA Private Key

Then to use with mosquitto-clients three files are required:

  • ca.crt – The Certificate authority certificate
  • client.crt – The client certifcate file
  • client.key – The client key
$ mosquitto_pub -h mqtt_demo -p 8883 -t "test" -m "test" --cafile ca.crt --cert client.crt --key client.key -d -i "test-client"
Client (null) sending CONNECT
Client (null) received CONNACK (0)
Client (null) sending PUBLISH (d0, q0, r0, m1, 'test', ... (4 bytes))
Client (null) sending DISCONNECT

We see our client conecting in the logs of the broker:

...
2021-04-09T14:44:29: New client connected from 192.168.1.142:58522 as test-client (p2, c1, k60).
2021-04-09T14:44:29: No will message specified.
2021-04-09T14:44:29: Sending CONNACK to test-client (0, 0)
2021-04-09T14:44:29: Received PUBLISH from test-client (d0, q0, r0, m0, 'test', ... (4 bytes))
2021-04-09T14:44:29: Received DISCONNECT from test-client
...

To put configure tthe device with this new certificate and key in the device, we have to extract theses data in the right format

To extract, the base64 of the certificate we can call this command:

$ cat client.crt | sed '1d;$d' | tr -d '\n'  | awk '{print $1}'
MIIBwzCCAWoCFELxAUFJwA1LGhR8c8pWaPQrCvdCMAoGCCqGSM49BAMCMGkxCzAJBgNVBAYTAkFVMRMwEQYDVQQIDApTb21lLVN0YXRlMSEwHwYDVQQKDBhJbnRlcm5ldCBXaWRnaXRzIFB0eSBMdGQxCzAJBgNVBAsMAkJFMRUwEwYDVQQDDAxNUVRUX0RFTU8gQ0EwHhcNMjEwNDA5MTMzODE2WhcNMjIwNDA0MTMzODE2WjBgMQswCQYDVQQGEwJBVTETMBEGA1UECAwKU29tZS1TdGF0ZTEhMB8GA1UECgwYSW50ZXJuZXQgV2lkZ2l0cyBQdHkgTHRkMRkwFwYDVQQDDBBURVNULUNMSUVOVC1ERU1PMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEgU5GPwkJTXsy3s5EdwrfPO6uzgGpcip2nEfXnUV8FL4agKp4sD5fJtdDJ3enGxeWqE4tNPU/STcWr3nts0vG8zAKBggqhkjOPQQDAgNHADBEAiAvzTcUjPxym1EZA264+K7n6YLgK8XC6x8yWRUCC23RAgIgSiTMCON4AajTlmuqZt8bKSqKnn7X5sUjA4hxFFsQqnI=

To extract the private key in hexadecimal format, use this command:

$ openssl pkey -in client.key -text --noout | sed '3,5!d' | sed 's/://g' | awk '{$1=$1};1' | tr -d '\n' | tr a-z A-Z | awk '{print $1}'
6F48F1627A5BA0A589AA78BF8B61400CE742FE35959E7271AE673AA1A1B99181

Then the json configuration file wiil looks like this:

{
	"type": "multiconf-v2",
	"config" : {
		"80": "",
		"86.string" : "mqtt_demo",
		"87" : "",
		"88" : "2102814100",
		"89" : "5514030A1E1E",
		"8B" : "",
		"8C" : "",
		"8D" : "",
		"8E" : "",
		"8F" : "",
		"C0" : "64"
	},
	"certificates" : {	
		"01.base64" : "MIIBwzCCAWoCFELxAUFJwA1LGhR8c8pWaPQrCvdCMAoGCCqGSM49BAMCMGkxCzAJBgNVBAYTAkFVMRMwEQYDVQQIDApTb21lLVN0YXRlMSEwHwYDVQQKDBhJbnRlcm5ldCBXaWRnaXRzIFB0eSBMdGQxCzAJBgNVBAsMAkJFMRUwEwYDVQQDDAxNUVRUX0RFTU8gQ0EwHhcNMjEwNDA5MTMzODE2WhcNMjIwNDA0MTMzODE2WjBgMQswCQYDVQQGEwJBVTETMBEGA1UECAwKU29tZS1TdGF0ZTEhMB8GA1UECgwYSW50ZXJuZXQgV2lkZ2l0cyBQdHkgTHRkMRkwFwYDVQQDDBBURVNULUNMSUVOVC1ERU1PMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEgU5GPwkJTXsy3s5EdwrfPO6uzgGpcip2nEfXnUV8FL4agKp4sD5fJtdDJ3enGxeWqE4tNPU/STcWr3nts0vG8zAKBggqhkjOPQQDAgNHADBEAiAvzTcUjPxym1EZA264+K7n6YLgK8XC6x8yWRUCC23RAgIgSiTMCON4AajTlmuqZt8bKSqKnn7X5sUjA4hxFFsQqnI=",
		"02.base64" : "MIICJjCCAc2gAwIBAgIUNPqK5VyOX1X2EiIGnXSYVEGJk4MwCgYIKoZIzj0EAwIwaTELMAkGA1UEBhMCQVUxEzARBgNVBAgMClNvbWUtU3RhdGUxITAfBgNVBAoMGEludGVybmV0IFdpZGdpdHMgUHR5IEx0ZDELMAkGA1UECwwCQkUxFTATBgNVBAMMDE1RVFRfREVNTyBDQTAeFw0yMTA0MDkxMDA5MDFaFw0yNjA0MDkxMDA5MDFaMGkxCzAJBgNVBAYTAkFVMRMwEQYDVQQIDApTb21lLVN0YXRlMSEwHwYDVQQKDBhJbnRlcm5ldCBXaWRnaXRzIFB0eSBMdGQxCzAJBgNVBAsMAkJFMRUwEwYDVQQDDAxNUVRUX0RFTU8gQ0EwWTATBgcqhkjOPQIBBggqhkjOPQMBBwNCAAQOMlwL4Y8FUlqSJacXUR8cXleCFps3XXDKyGuTm2i26S4aoGP0NQ6P75KRU3sPuqYcQR4hvZ+ZhtBR2ptVlZ4zo1MwUTAdBgNVHQ4EFgQUKzhMLyefO1ME9FkoAx/mYPBPYAgwHwYDVR0jBBgwFoAUKzhMLyefO1ME9FkoAx/mYPBPYAgwDwYDVR0TAQH/BAUwAwEB/zAKBggqhkjOPQQDAgNHADBEAiB4aWr0S1TIpK5eja+xgQeT5XDtrH3ZJa3UqApT74JqYQIgXic1IcCTaTWEeEI2hrC1OKHRdS0VB56t1FqauQXY/lI="
	},
	"atecc": {
		"01" : "6F48F1627A5BA0A589AA78BF8B61400CE742FE35959E7271AE673AA1A1B99181"
	}
}

Again we will edit the register 88 to use certifictae and key 01. The key will be store inside the ATECC.

Register Content
0280 IPv4 Settings IPv4 parameters (address, mask, gateway, DNS servers)
Leave empty for DHCP operation
0286 MQTT : Server Hostname of MQTT server:
"mqtt_demo" or the IP address of your broker
0287 MQTT : Port Listen port of the MQTT server
Leave empty for default value 8883 if TLS is used
0288 MQTT : TLS Options Use the following settings:
- TLS enabled
- SNI disabled
- Don't verify CN (Server Name)
- Verify server CA certificate
- Verify public key only
- Server certificate is in slot 7 (02)
- Enable client authentication
- Client certificate is in slot 1 (01)
- Client private key is in ATECC
- Client private key is in slot 1 (01)
- Don't chain CA certicate with client certificate

The value to put in the register is therefore 2102814100
0289 MQTT : Client Options Use the following settings:
- QoS used for subscribing: 1
- QoS used for publishing: 1
- Don't create topic before subscribe
- Disable Last Will Message
- Disable Retained Messages
- Connection timeout: 30s
- Response timeout: 3s
- Keep alive interval: 10s
- Status publish interval: 30s
- Reconnect interval: 30s

The value to put in the register is therefore 5014030A1E1E
028B MQTT : Login Must be empty
028C MQTT : Password Must be empty
028D MQTT : Client ID Leave empty. Doing so, the device uses its Serial Number as Client ID.
028E MQTT : Topic prefix Leave empty. Doing so, the device's topics are under "springcard/springcore".
028F MQTT : Device ID Leave empty. Doing so, the device uses its Serial Number as Device ID.
02C0 Main configuration : Profile Set to 64 for Smart Reader operation through MQTT client

We can verify in the logs that the device is connected to the broker:

...
2021-04-09T14:59:34: New connection from 192.168.1.13:63224 on port 8883.
2021-04-09T14:59:40: New client connected from 192.168.1.13:63224 as 000000000003 (p2, c1, k10).
2021-04-09T14:59:40: Will message specified (24 bytes) (r1, q0).
2021-04-09T14:59:40:    springcard/springcore/000000000003/status
2021-04-09T14:59:40: Sending CONNACK to 000000000003 (0, 0)
2021-04-09T14:59:40: Received SUBSCRIBE from 000000000003
...

Congratulations if you reached the end of this tutorial and everything works!

We could also see how to implements ACLs with TLS intremediate's certificate and a more complex architcture using Websockets, bind_address, JS client's library with Paho-MQTT...

To do so, SpringCard developped a Mosquitto plugin which is able to parse TLS certificates.

Don't hesitate to contact us at info@springcard.com for more information about these matters.