RCM67xx https client/server

Could somebody please clarify the following points …

a. When using the RCM67xx as a client

I would like to be able to POST data from an RCM67xx module to a cloud-based server (probably AWS).
I will be using a http connection secured with TLS v1.2
The data needs to be sent as JSON

I have experimented with the Dynamic C 10.72E https client samples (blocking and non-blocking) and using verbose mode I can see TLS working nicely in most cases.

The sample code imports 4 certificates (provided by Digi as part of the Dynamic C installation).
Are these certificates required ? The code seems to work without them.

Is it necessary for me to create my own certificate and include it in my code to allow my RCM67xx module to identify itself to the AWS server ?

If so, how would I do this ?

I have read about self-signed certificates, and I know that these can be created using openssl, but will this be enough ? Or do I need to embed a certificate from AWS into my client code ?

b. When using the RCM67xx as a server

I have a web server which can be accessed over LAN at a private IP address such as 192.168.0.x or 192.168.1.y
I can access the server from the WAN side using port forwarding.
The web server is currently http only.

Is it possible to force the web server to use https i.e. can we get the padlock icon to appear in the browser ?

I can see from the examples that Dynamic C supports importing certificates and I know that v10.72E supports TLS v1.2.
I have experimented with the https examples, but they seem to focus on using the RCM67xx as a client.
I cannot find a https web server example.

What are the steps required to implement a https web server, and what are the limitations when doing so ?

Many thanks for any help

1 Like

If you’re using the Samples/tcpip/http/HTTPS_CLIENT.C sample, it includes a my_server_policy() callback. If you look through that callback, you’ll see code that dumps details of the certificate, and makes use of the x509_validate_hostname() API to compare the hostname you’re using to connect with the hostname in the certificate. You can also uncomment a line of code toward the end to have it reject connections where the server certificate isn’t signed by one of your CA certs.

You register that callback in the httpc_set_tls() API call. There’s a lot of documentation on that API that I won’t copy here, but it does explain the trusted parameter in my_server_policy(). In Dynamic C, put your cursor somewhere inside the name and hit CTRL-H to pull up the documentation. That API also has a parameter where you can specify a client certificate if required by the server you’re connecting to. I believe there are some IoT setups where you use client certificates as an additional security measure.

The CA verification can be tricky when the server you’re connecting to updates its certificates to use a new CA. You’ll need to watch for announcements of possible CA changes, and have a method to update the CA list on your remote devices. It could be helpful to have backup servers (that you have direct control of the TLS certificates) where your device can download an updated CA list.

It’s been some time since I’ve done TLS testing, but if you can connect to AWS (or your target server) from a regular web browser, you should be able to download the chained certificates for the site and identify the CA used. For example, in Safari on macOS, you can click the lock icon to view the certificate chain, and then click-and-drag the certificate icon for any link of the chain to your desktop to get the .cer file.

For your second question, the HTTPS Server samples are in the Samples/tcpip/SSL/HTTPS/ directory. Server certificates on embedded servers can be tricky, since you typically don’t have a hostname you can tie to the certificate, and it might not be possible to securely store the private half of the certificate on the device. You could provide an interface for the end-user of the RCM6700-based product to install a certificate that they’ve created, and just rely on them keeping the hardware physically secure so an attacker can’t dump the SPI flash to obtain the private certificate.

I think that by default, you’ll end up using a self-signed certificate on the device. Either the same certificate on all of your hardware, or maybe one with a hostname that includes the MAC address or a serial number. When users connect to the device, they’ll need to tell their web browser to trust the connection since the certificate won’t be signed by a root CA, and will almost certainly have a hostname mismatch.

I hope these answers help you move forward. Feel free to ask more questions as you make progress.

Thanks for your prompt reply.

Focusing on the server side of things for the moment (RCM6760 on private LAN) …

I followed the instructions in SSL_Utilities\README.md and used openssl to generate a self-signed certificate as follows …

Step 1 - create the certificate and private key by entering the following line into a command prompt window (use .\openssl if required)

openssl req -x509 -sha256 -nodes -days 365 -newkey rsa:2048 -keyout mycert.key -out mycert.crt -config …\openssl.cnf

This generates …

WARNING: can’t open config file: /usr/local/ssl/openssl.cnf (DOES THIS MATTER ? It still runs.)

Generating a 2048 bit RSA private key

etc. etc.

Step 2 - convert the private key to PKCS#1 format

openssl rsa -in mycert.key -out mycert_rsa.key

The resulting files (mycert.crt and mycert_rsa.key) can be imported into the Dynamic C sample program SSL_STATIC.C
(place the files into the cert sub-directory)

If I use SSL_CERT_VERBOSE then when I run the program I see the following output from stdio …

sock_init_or_exit: hit any key to terminate
Network default interface up at IP=192.168.1.102 mask=255.255.255.0
SSL_new_cert: cert=00213BA4 addr=0000E760 type=2 append=0
crypto_public_key_import() returns 000AFAB0
SSL_new_cert: OK
SSL_set_private_key: cert=00213BA4 addr=0000ED0C type=2
crypto_private_key_import() returns 000B02F8
replacing old public key at 000AFAB0
SSL_set_private_key: OK
SSL_free_cert: cert=00213B82 format=0

I believe that this shows the certificate being imported successfully.

However, when I access the web page (https://192.168.1.102 in my case) I get …

NET::ERR_CERT_AUTHORITY_INVALID

This is because modern browsers do not trust self-signed certificates.

I have tried installing the certificate into my browser via the Settings → Privacy page but this doesn’t seem to help.

If I try to purchase a certificate online, I am asked to provide a domain name, and to then prove that I own that domain.
This obviously cannot be done for a private IP address.

Does anybody know how can this be resolved ?

To be clear : the goal is to have secure access to the web server via https with no browser warnings and a visible padlock icon in the address bar.

This problem isn’t unique to the Rabbit; it impacts all IoT devices.

The challenge of self-signed certificates is that they don’t protect against man-in-the-middle attacks.

This question on Security StackExchange provides a lot of details, and might be enough for you to find a workable solution.