SETTING UP CERTIFICATES FOR HTTPS REQUESTS FROM A TIBBO DEVICE
Applies to: Tibbo G3 devices (e.g. TPP2W(G3))
Sample project: HTTPS_GET
OVERVIEW
The HTTPS_GET sample sends an HTTPS GET request from the Tibbo device to a web server and prints the response. It obtains its address with DHCP, resolves the server's name with DNS, opens a TLS connection and sends the request when you press the MD button.
As a TLS client, the device checks the certificate the web server presents. For that it needs one file: the certificate of whoever issued the server's certificate, called the CA certificate. It is stored as ca_cert.der, added to the project and loaded with sock.tlsinit() before the handshake. The device does not need a private key or a certificate of its own.
Where ca_cert.der comes from depends on the server:
- Case A - A local web server with a self-signed certificate, for example XAMPP on your PC. The server's certificate signs itself, so ca_cert.der is the server's own certificate.
- Case B - A public web server with a certificate from a certificate authority, for example https://aws.amazon.com. ca_cert.der is that authority's root certificate.
Case A is covered with both ECDSA P-256 and RSA 2048 keys; we suggest using ECDSA P-256 for higher security and connection speed versus RSA 2048. The socket buffers in the sample (6 pages RX and TX) are sized for ECDSA; set TLS_RX_BUFF and TLS_TX_BUFF to 8 pages for RSA 2048 and for public servers.
WHAT YOU NEED
- OpenSSL 3.x on your PC.
- TIDE with the HTTPS_GET sample project.
- For Case A: XAMPP (or another web server that supports TLS 1.3) on the PC.
- For Case B: internet access for the device and a reachable DNS server.
All commands below are written on a single line so they work the same in Command Prompt, PowerShell and Git Bash.
IMPORTANT: THE CERTIFICATE MUST MATCH SERVER_HOST
The device passes SERVER_HOST to sock.tlshandshake() and also sends it as the HTTP Host header. The server's certificate must list that exact IP address or host name in its Subject Alternative Name (SAN). Public servers' certificates already list their host names; for a local server you set it yourself in Part A1.
PART 1 - HOW THE SAMPLE WORKS
The settings are in global.tbh:
#define USE_DHCP 1 1 = DHCP, 0 = the static values below
const DEVICE_IP = "192.168.1.218"
const DEVICE_MASK = "255.255.255.0"
const DEVICE_GW = "192.168.1.1"
const DNS_SERVER = "8.8.8.8"
const SERVER_HOST = "192.168.1.70" must match the name or IP in the certificate
const SERVER_PORT = 443
const SERVER_PATH = "/"
#define CA_CERT "ca_cert.der"
#define TLS_RX_BUFF 6 use 8 for RSA 2048 and public servers
#define TLS_TX_BUFF 6
const REQUEST_TIMEOUT_TICKS = 60 give up after 60 x 0.5 s = 30 sWhen the device has an address it prints "HTTPS_GET ready, IP ...". Each press of the MD button then runs one request:
- If SERVER_HOST is a host name, the device resolves it through DNS_SERVER. If it is an IP address, this step is skipped.
- The device opens a TCP connection to SERVER_PORT.
- When the connection is established (PL_SST_EST_AOPENED), it loads ca_cert.der and starts the handshake with sock.tlsinit(romfile.offset) and sock.tlshandshake(SERVER_HOST).
- When the handshake completes (PL_SST_EST_TLS), it sends "GET SERVER_PATH HTTP/1.1" with "Connection: close".
- It prints the response until the server closes the connection. A request that has not finished within 30 seconds is cancelled.
The sample uses the DHCP, DNS and socket-allocation libraries, and sets #define WLN_AVAILABLE 0 in global.tbh so that these libraries leave out their Wi-Fi code. On a platform that has Wi-Fi, the compiler shows a "preprocessor redefinition" warning for this line. The warning is expected.
CASE A - A LOCAL SERVER WITH A SELF-SIGNED CERTIFICATE
PART A1 - CREATE THE SERVER CERTIFICATE
The examples use a PC at 192.168.1.70. Replace it everywhere with the address of your server.
Option A: ECDSA P-256
Step 1. Create a configuration file named server_ec.cnf with this content:
[req]
prompt = no
distinguished_name = dn
x509_extensions = v3_req
[dn]
CN = 192.168.1.70
[v3_req]
basicConstraints = critical,CA:TRUE
subjectAltName = @alt_names
[alt_names]
IP.1 = 192.168.1.70
Step 2. Generate the private key:
openssl ecparam -name prime256v1 -genkey -noout -out server_ec.key
Step 3. Create the self-signed certificate, valid for 10 years:
openssl req -new -x509 -key server_ec.key -out server_ec.crt -days 3650 -config server_ec.cnf
Option B: RSA 2048
Step 1. Create a configuration file named server_rsa.cnf with this content:
[req]
default_bits = 2048
prompt = no
distinguished_name = dn
x509_extensions = v3_req
[dn]
CN = 192.168.1.70
[v3_req]
basicConstraints = critical,CA:FALSE
keyUsage = critical,digitalSignature,keyEncipherment
extendedKeyUsage = serverAuth
subjectAltName = @alt_names
[alt_names]
IP.1 = 192.168.1.70
Step 2. Generate the private key:
openssl genrsa -out server_rsa.key 2048
Step 3. Create the self-signed certificate, valid for 10 years:
openssl req -new -x509 -key server_rsa.key -out server_rsa.crt -days 3650 -config server_rsa.cnf
Check the certificate and confirm the SAN contains the server's address (use server_rsa.crt for RSA):
openssl x509 -in server_ec.crt -noout -ext subjectAltNameExpected output:
X509v3 Subject Alternative Name: IP Address:192.168.1.70The .crt and .key files are used by the server on the PC. The .key file is secret and stays on the PC; it never goes to the Tibbo device.
PART A2 - CREATE ca_cert.der FOR THE DEVICE
For a self-signed certificate, the server's certificate is also the CA certificate the device needs. Convert it to DER (use server_rsa.crt for RSA):
openssl x509 -in server_ec.crt -outform DER -out ca_cert.derCheck the file:
openssl x509 -inform DER -in ca_cert.der -noout -subject -ext subjectAltName
PART A3 - CONFIGURE XAMPP FOR HTTPS
- Copy server_ec.crt and server_ec.key (or the RSA pair) into the XAMPP Apache configuration folders, for example C:\xampp\apache\conf\ssl.crt\ and C:\xampp\apache\conf\ssl.key\.
- Open C:\xampp\apache\conf\extra\httpd-ssl.conf and point these two lines at your files:
SSLCertificateFile "conf/ssl.crt/server_ec.crt"
SSLCertificateKeyFile "conf/ssl.key/server_ec.key"- Restart Apache from the XAMPP Control Panel.
- Put a small test file in C:\xampp\htdocs\, or use the default page.
You can check the server from the PC before involving the device:
openssl s_client -connect 192.168.1.70:443 -CAfile server_ec.crt -verify_ip 192.168.1.70Look for "Verify return code: 0 (ok)". Optionally, install server_ec.crt in Windows as a trusted root so that your own browser also trusts the server, as described in Part 4 of the TLS server article [LINK: TLS_Inbound_SSL_MULTI_SERVER]. The device does not need this.
PART A4 - CONFIGURE AND RUN HTTPS_GET
- Copy ca_cert.der into the HTTPS_GET project folder, replacing the existing file, and make sure it is part of the project in TIDE. The name must match CA_CERT.
- In global.tbh, set SERVER_HOST to the server's address (for example "192.168.1.70"), SERVER_PORT to 443 and SERVER_PATH to the page or file to fetch.
- Build the project, upload it, wait for "HTTPS_GET ready" and press MD.
The debug output shows each step and then the server's response:
Connecting to 192.168.1.70:443...
TCP connected. Starting TLS...
TLS handshake started...
TLS established. Sending GET /
HTTP/1.1 200 OK
...
Response complete (server closed the connection)
CASE B - A PUBLIC SERVER WITH A CA-ISSUED CERTIFICATE
Public servers use certificates issued by a certificate authority. The server sends its own certificate and any intermediate certificates during the handshake, so the device only needs the root certificate at the top of the chain. The example uses https://aws.amazon.com.
PART B1 - FIND OUT WHICH ROOT THE SERVER USES
Run this on your PC (in Command Prompt, add "< NUL" at the end so the command exits by itself):
openssl s_client -connect aws.amazon.com:443 -servername aws.amazon.com -showcertsScroll to the last certificate in the output and read its "i:" (issuer) line. That is the root you need, for example "CN = Amazon Root CA 1".
PART B2 - GET THE ROOT CERTIFICATE
Either method works.
Method A - From the certificate authority's website
Download the root certificate from the authority's repository. For Amazon this is the Amazon Trust Services repository (www.amazontrust.com/repository). If the file is in PEM format (text beginning with "-----BEGIN CERTIFICATE-----"), convert it to DER:
openssl x509 -in AmazonRootCA1.pem -outform DER -out ca_cert.derIf it is already DER (binary), just rename it to ca_cert.der.
Method B - From Windows, which already trusts the major roots
- Run "Manage computer certificates" (certlm.msc).
- Open Trusted Root Certification Authorities > Certificates.
- Find the root named in Part B1, for example "Amazon Root CA 1".
- Right-click it and choose All Tasks > Export.
- Choose "DER encoded binary X.509 (.CER)" and save the file.
- Rename the file to ca_cert.der.
Check the file:
openssl x509 -inform DER -in ca_cert.der -noout -subject -enddate
PART B3 - CONFIGURE AND RUN HTTPS_GET
- Copy ca_cert.der into the HTTPS_GET project folder, replacing the existing file, and make sure it is part of the project in TIDE.
- In global.tbh set:
const SERVER_HOST = "aws.amazon.com"
const SERVER_PORT = 443
const SERVER_PATH = "/robots.txt"
#define TLS_RX_BUFF 8
#define TLS_TX_BUFF 8A small path such as /robots.txt keeps the response short. A full home page can be hundreds of kilobytes, and it all goes to the debug output. Public servers often send a long RSA certificate chain, hence the 8-page buffers.
- The device needs internet access and a working DNS server: leave USE_DHCP at 1 on a network with DHCP, or set the static values and DNS_SERVER.
- Build, upload, wait for "HTTPS_GET ready" and press MD. The device resolves the name, connects, completes the handshake and prints the response.
Root certificates are valid for many years, but authorities do change them eventually. If a server that used to work starts failing the handshake, repeat Part B1 to check whether its root has changed.
TROUBLESHOOTING
"MD: no IP address yet"
DHCP has not completed. Check the network, or set USE_DHCP to 0 and use the static values.
A DNS error, or "Request ended: timed out" while resolving
Check DNS_SERVER and that the device can reach it. For a local server, use its IP address as SERVER_HOST to skip DNS.
"tlsinit FAILED"
ca_cert.der could not be loaded. Check that it is in the project, that its name matches CA_CERT, and that it is in DER format.
"TLS handshake FAILED - resetting"
For Case A, ca_cert.der must be made from the exact certificate the server uses. For Case B, it must be the root reported in Part B1. SERVER_HOST must appear in the server certificate's SAN. Use 8-page buffers for RSA 2048 and public servers. The server must support TLS 1.3.
The response is cut short or the request times out
Use a smaller SERVER_PATH, or increase REQUEST_TIMEOUT_TICKS.
Comments
0 comments
Article is closed for comments.