Introduction
This comprehensive guide covers SSL/TLS security implementation on NetBurner embedded devices. Whether you're securing a web interface, IoT communication, or industrial control system, this guide provides practical solutions for establishing encrypted, authenticated connections.
What You'll Learn:**
- Core SSL/TLS concepts explained clearly
- Multiple implementation approaches from simple to advanced
- Certificate management strategies
- Common issues and their solutions
- Production-ready deployment practices
Understanding SSL/TLS Fundamentals
Note: This document uses "SSL" as shorthand for SSL/TLS protocols. Modern implementations use TLS (Transport Layer Security), the successor to SSL.
The Security Problem
In a normal network connection, data travels in plain text. This creates two critical vulnerabilities:
┌────────┐ ┌────────┐
│ Client │─────────────────────────────────────>│ Server │
└────────┘ Unencrypted Data └────────┘
Vulnerability 1: Eavesdropping**
┌────────┐ ┌────────┐
│ Client │──────────┐ ┌────│ Server │
└────────┘ │ │ └────────┘
v ^
┌──────────┐ │
│ Attacker │─────────────────┘
│(Sniffing)│
└──────────┘
"I can read everything!"
Vulnerability 2: Man-in-the-Middle (MITM)**
┌────────┐ ┌────────┐
│ Client │──────────┐ ┌────│ Server │
└────────┘ │ │ └────────┘
v ^
┌──────────┐ │
│ Attacker │─────────────────┘
│ (Proxy) │
└──────────┘
"I can read AND modify everything!"
How SSL/TLS Solves These Problems
SSL/TLS provides three critical security features:
- Encryption: Data is scrambled so eavesdroppers see gibberish
- Authentication: Verify you're talking to the real server (not an attacker)
- Integrity: Detect if data has been tampered with
The Trust Chain: How Authentication Works
SSL/TLS uses a "chain of trust" similar to how we trust professionals:
Real-World Analogy: Trusting a Doctor
┌─────────────────┐
│ Medical School │ <── We trust the institution
└────────┬────────┘
│ issues diploma
v
┌─────────┐
│ Hospital│ <── Hospital verifies the diploma
└────┬────┘
│ employs
v
┌────────┐
│ Doctor │ <── We trust the doctor by extension
└────────┘
SSL/TLS Certificate Chain
┌──────────────────────┐
│ Root CA │ <── Trusted by browsers/clients (pre-installed)
│ (e.g., DigiCert) │
└──────────┬───────────┘
│ signs
v
┌──────────────────────┐
│ Intermediate CA │ <── Issues certificates for organizations
└──────────┬───────────┘
│ signs
v
┌──────────────────────┐
│ Server Certificate │ <── Your device's identity
│ CN: yourdevice.com │
└──────────────────────┘
Key Components of a Certificate:**
- Identity (Common Name/CN) - Who this certificate represents
- Public Key - Like an open padlock anyone can use to encrypt
- Signature - Cryptographic proof from a trusted CA
Public Key Cryptography Simplified
Think of it like a special mailbox:
┌─────────────────────────────────────────┐
│ Public Key = Open Padlock │
│ (Anyone can lock, share freely) │
│ │
│ ┌───────┐ │
│ │ [BOX] │ <── Locked Box │
│ │ [LCK] │ (Encrypted Data) │
│ └───────┘ │
│ │
│ Private Key = Key to Padlock │
│ (Only owner can unlock, KEEP SECRET!) │
│ │
│ ┌───────┐ │
│ │ [BOX] │ <── Unlocked Box │
│ │ [GEM] │ (Decrypted Data) │
│ └───────┘ │
└─────────────────────────────────────────┘
Critical Security Principle:**
[LOCK] The system is only as secure as the private key. If an attacker gets your private key, they can decrypt all traffic and impersonate your device.
Certificate Types at a Glance
| Type | Trust Level | Browser Warnings | Best For | Cost |
| Self-Signed | Low | [!] Yes | Development, testing, internal networks | Free |
| Private CA | Medium | [!] Yes (until CA installed) | Enterprise deployments, controlled environments | Free |
| Public CA | High | [OK] No | Production, public-facing devices | Varies |
| ACME (Let's Encrypt) | High | [OK] No | Production with public DNS | Free |
Quick Start Guide
For SSL Servers (Your NetBurner Device)
Option 1: Automatic (Recommended for Production)
If you have a public DNS name:**
#include <acmeservlet.h>
void UserMain(void *pd) {
AcmeConfig config;
config.domain = "mydevice.example.com";
StartAcmeHttps(config);
printf("Secure HTTPS server running\n");
}
#define TICKS_PER_SECOND
System clock ticks per second.
Definition constants.h:49
void init()
System initialization. Ideally called at the beginning of all applications, since the easiest Recover...
bool WaitForActiveNetwork(uint32_t ticks_to_wait=120 *TICKS_PER_SECOND, int interface=-1)
Wait for an active network connection on at least one interface.
If you only have local/private network:**
#include <init.h>
#include <startnet.h>
void UserMain(void *pd) {
printf("HTTPS server running (self-signed)\n");
}
void StartHttps(uint16_t ssl_port, uint16_t http_port)
Start the HTTPS secure web server.
For SSL Clients (Connecting to Servers)
#include <ssl.h>
#include <nettcp.h>
extern const char letsEncryptCA[];
extern const int letsEncryptCA_len;
void ConnectSecurely() {
int fd =
connect(
"api.example.com", 443);
if (ssl) {
SSL_write(ssl, "GET / HTTP/1.1\r\n\r\n", 18);
SSL_close(ssl);
}
}
bool SSL_AddCertToClientCaList(const unsigned char *certBuff=nullptr, uint32_t certBuffSize=0, uint16_t certBuffFormat=SSL_FILETYPE_PEM)
Attempts to add a cert to the Certificate Authority List to the client SSL context.
void SslInit()
This function initializes the SSL library.
int SSL_connect(IPADDR ip, uint16_t remotePort, uint32_t timeout, const char *commonName, bool verifyPeer=false, bool waitForNegotiation=true, const unsigned char *certBuff=nullptr, uint32_t certBuffSize=0, uint16_t certBuffFormat=SSL_FILETYPE_PEM, int intf=-1)
SSL mirror of the TCP::connect() call.
int connect(const IPADDR &ipAddress, uint16_t remotePort, uint32_t timeout)
Establish a TCP connection to a remote host.
Definition tcp.h:1547
Certificate Types and Use Cases
Decision Matrix
Need Public Access?
│
┌─────────┴─────────┐
YES NO
│ │
Have DNS name? Multiple devices?
│ │
┌─────┴─────┐ ┌─────┴─────┐
YES NO YES NO
│ │ │ │
v v v v
Use ACME Use Public Private Self-Signed
(Let's Encrypt) CA CA (Simplest)
1. Self-Signed Certificates
What It Is:** Device acts as its own Certificate Authority
Visual Flow:**
NetBurner Device
┌──────────────────────────┐
│ 1. Generate Key Pair │
│ 2. Create Certificate │
│ 3. Sign with Own Key │
│ 4. Use for Connections │
└──────────┬───────────────┘
│
v
Browser/Client
┌──────────────────────────┐
│ [!] Certificate Warning │
│ "Not Trusted" │
│ │
│ [Proceed Anyway] │
└──────────────────────────┘
When to Use:**
2. Private Certificate Authority (CA)
What It Is:** You create your own CA and sign device certificates
Visual Flow:**
Step 1: Create Your CA
┌─────────────────────┐
│ Computer with │
│ OpenSSL/CreateCerts │
│ │
│ 1. Create CA Key │
│ 2. Create CA Cert │
└─────────┬───────────┘
│
v
Step 2: Sign Device Certs
┌─────────────────────┐
│ For each device: │
│ 1. Generate Key │
│ 2. Create CSR │
│ 3. Sign with CA │
└─────────┬───────────┘
│
v
Step 3: Deploy
┌──────────────────────┬──────────────────────┐
│ Install CA Cert on │ Install Device Cert │
│ All Clients │ on Each Device │
└──────────────────────┴──────────────────────┘
When to Use:**
- [YES] Multiple devices in controlled environment
- [YES] Corporate/enterprise deployment
- [YES] Need certificate management
[YES] Air-gapped or private networks
Advantages:**
- [YES] One-time CA installation for all clients
- [YES] Central control over certificate issuance
- [YES] Can revoke compromised certificates
[YES] No external dependencies
Limitations:**
- [NO] More complex initial setup
- [NO] Must manually manage certificate expiration
[NO] CA certificate must be distributed to all clients
NetBurner Implementation:**
Use the provided scripts in \nburn\CreateCerts\:
# Step 1: Create your CA (one time)
cd C:\nburn\CreateCerts\ECDSA
createCA.bat
# Step 2: Create device certificate
createDeviceCert.bat mydevice.example.com
# Step 3: Convert to C++ for NetBurner
compfile device.key comp_key comp_key_len key.cpp
compfile device.crt comp_cert comp_cert_len cert.cpp
extern const unsigned char comp_cert[];
extern const int comp_cert_len;
extern const unsigned char comp_key[];
extern const int comp_key_len;
void UserMain(void *pd) {
SSL_InstallCertificate(comp_cert, comp_cert_len,
comp_key, comp_key_len);
}
3. Public CA Certificates
What It Is:** Purchase certificates from trusted authorities (DigiCert, GoDaddy, etc.)
Visual Flow:**
Step 1: Generate CSR
┌──────────────────────┐
│ Device/Computer │
│ 1. Create Key │
│ 2. Generate CSR │
└──────────┬───────────┘
│
v
Step 2: Submit to CA
┌──────────────────────┐
│ Certificate Authority│
│ (DigiCert, etc.) │
│ │
│ 1. Verify Domain │
│ 2. Issue Certificate │
└──────────┬───────────┘
│
v
Step 3: Install
┌──────────────────────┐
│ NetBurner Device │
│ 1. Install Cert │
│ 2. Install Chain │
└──────────────────────┘
When to Use:**
- [YES] Public-facing production devices
- [YES] Need universal trust (no warnings)
- [YES] Customer/client access
[YES] Professional appearance required
Advantages:**
- [YES] No browser warnings
- [YES] Pre-trusted by all clients
- [YES] Professional appearance
[YES] Insurance/warranty often included
Limitations:**
- [NO] Annual costs ($50-$500+)
- [NO] Manual renewal process
- [NO] Requires public DNS name
[NO] Validation requirements
Process:**
- Generate Certificate Signing Request (CSR):
openssl genrsa -out device.key 2048
openssl req -new -key device.key -out device.csr
# Enter device domain name as Common Name
- Submit CSR to CA and complete verification
- Receive certificate and chain files
- Combine certificate with chain:
# Create complete chain file
cat device.crt intermediate.crt root.crt > device_chain.crt
- Convert and install on NetBurner (same as Private CA method)
4. ACME (Automated Certificate Management)
What It Is:** Automated certificate issuance from Let's Encrypt or BuyPass
Visual Flow:**
┌──────────────────────────────────────────────────────┐
│ NetBurner Device with ACME │
│ │
│ ┌──────────────────────────────────────────────┐ │
│ │ 1. Request Certificate from Let's Encrypt │ │
│ └─────────────────┬────────────────────────────┘ │
│ v │
│ ┌──────────────────────────────────────────────┐ │
│ │ 2. Let's Encrypt Verifies Domain Ownership │ │
│ │ (HTTP-01 Challenge) │ │
│ └─────────────────┬────────────────────────────┘ │
│ v │
│ ┌──────────────────────────────────────────────┐ │
│ │ 3. Certificate Issued & Installed │ │
│ └─────────────────┬────────────────────────────┘ │
│ v │
│ ┌──────────────────────────────────────────────┐ │
│ │ 4. Auto-Renewal Before Expiration (90 days) │ │
│ └──────────────────────────────────────────────┘ │
└──────────────────────────────────────────────────────┘
│
v
Browser/Client
┌──────────────────────┐
│ [OK] Trusted Connect │
│ No Warnings │
└──────────────────────┘
When to Use:**
- [YES] Production devices with public DNS
- [YES] Need automatic renewal
- [YES] Want trusted certs without cost
[YES] Device accessible from internet
Requirements:**
- [YES] Public DNS name pointing to device
- [YES] Device reachable on port 80 (for validation)
[YES] NNDK 3.5.0 or later
Advantages:**
- [YES] Completely automatic
- [YES] Free trusted certificates
- [YES] Auto-renewal every 60 days
[YES] No manual certificate management
Limitations:**
- [NO] Requires public internet access
- [NO] Must have DNS name (no IP-only)
[NO] Shorter validity (90 days vs 1 year)
NetBurner Implementation:**
#include <acmeservlet.h>
void UserMain(void *pd) {
AcmeConfig config;
config.domain = "iot-device.example.com";
config.acmeServer = ACME_LETSENCRYPT_PRODUCTION;
int result = StartAcmeHttps(config);
if (result == 0) {
printf("ACME HTTPS server started successfully\n");
printf("Certificate will auto-renew before expiration\n");
} else {
printf("ACME setup failed: %d\n", result);
}
}
void EnableSystemDiagnostics()
Turn on the diagnostic reports from the config page.
Use Case Decision Table
| Scenario | Recommended Method | Why |
| Development/Testing | Self-Signed | Fastest, simplest |
| Internal corporate network, 10+ devices | Private CA | Central management, one-time client setup |
| Public website/API | ACME or Public CA | Trusted by all browsers |
| Air-gapped system | Private CA or Self-Signed | No external dependencies |
| IoT fleet with DNS names | ACME | Automatic, scalable, free |
| Single device, few users | Self-Signed | Adequate for small scale |
| Requires IP address (no DNS) | Self-Signed or Private CA | ACME requires DNS |
| Critical infrastructure | Public CA | Professional support, insurance |
Implementation Methods
Method 1: Automatic Onboard Certificate Generation
Simplest approach - certificates generated automatically on first use.**
How It Works
First Boot / Certificate Needed
│
v
┌──────────────────────────────────┐
│ Check: Certificate exists? │
└──────┬────────────────────┬──────┘
NO YES
│ │
v v
┌──────────────────┐ ┌──────────────┐
│ Generate New │ │ Use Existing │
│ Self-Signed │ │ Certificate │
│ Certificate │ └──────────────┘
└──────────┬───────┘
│
v
┌──────────────────────────────────┐
│ Store in Non-Volatile Memory │
└──────────────────────────────────┘
Basic Implementation
#include <init.h>
const char *AppName = "Secure Device";
void UserMain(void *pd) {
printf("HTTPS Server: %s\n", AppName);
printf("Certificate auto-generated if needed\n");
while (1) {
}
}
Advanced: Auto-Regeneration
Enable automatic regeneration when certificates expire:
#define ENABLE_AUTOCERT_REGEN
#define AUTO_CERT_GEN_CHECK (60 * 20)
Customizing Certificate Generation
#include <ssl.h>
void CustomCertCallback(SslCertAttributes_t *attrs) {
attrs->country = "US";
attrs->state = "California";
attrs->locality = "San Diego";
attrs->organization = "My Company";
attrs->commonName = "mydevice.local";
attrs->altNames = "mydevice.local,192.168.1.100,#LOCAL";
}
void UserMain(void *pd) {
SSL_SetCertificateCallback(CustomCertCallback);
}
Method 2: ACME Automated Certificates
Production-ready trusted certificates with automatic renewal.**
Complete ACME Example
#include <init.h>
#include <acmeservlet.h>
#include <nbrtos.h>
const char *AppName = "ACME Secure Device";
void UserMain(void *pd) {
printf("Device IP: %s\n", GetIP().c_str());
printf("Waiting for DNS resolution...\n");
AcmeConfig config;
config.domain = "iot-device.example.com";
config.acmeServer = ACME_LETSENCRYPT_PRODUCTION;
config.acceptTerms = true;
printf("Starting ACME certificate process for: %s\n", config.domain);
int result = StartAcmeHttps(config);
if (result == 0) {
printf("[OK] ACME HTTPS server running\n");
printf("Certificate valid for 90 days\n");
printf("Auto-renewal occurs at 60 days\n");
} else {
printf("[ERR] ACME failed with error: %d\n", result);
printf("Check: DNS resolution, firewall, port 80 access\n");
}
while (1) {
}
}
ACME Troubleshooting Checklist
Prerequisites Check:
[ ] Device has public IP address
[ ] DNS A record points to device IP
[ ] Port 80 open and accessible from internet
[ ] Port 443 open for final HTTPS
[ ] NTP time synchronized (critical!)
[ ] Sufficient free memory (>50KB)
Common Issues:
[X] DNS not resolving -> Check DNS propagation (nslookup)
[X] Port 80 blocked -> Check firewall rules
[X] Challenge fails -> Verify HTTP-01 accessibility
[X] Time sync error -> Enable and wait for NTP
[X] Memory allocation fail -> Check heap usage
Method 3: Manual Certificate Installation
For private CAs or purchased certificates.**
Step-by-Step Process
Step 1: Generate Certificate Files**
Using NetBurner CreateCerts scripts:
# Navigate to CreateCerts directory
cd C:\nburn\CreateCerts\ECDSA
# Create CA (one time, if needed)
createCA.bat
# Create device certificate
createDeviceCert.bat mydevice.example.com
# Output files:
# - device.key (private key - KEEP SECRET!)
# - device.crt (certificate)
# - ca.crt (CA certificate)
Step 2: Convert to C++ Code**
# Convert key
compfile device.key comp_key comp_key_len key.cpp
# Convert certificate
compfile device.crt comp_cert comp_cert_len cert.cpp
# Optional: Convert CA for chain
compfile ca.crt comp_ca comp_ca_len ca.cpp
Step 3: Add to Project**
YourProject/
├── src/
│ ├── main.cpp
│ ├── key.cpp <- Add these
│ ├── cert.cpp <- Add these
│ └── ca.cpp <- Optional
└── makefile
Update makefile if using command line builds:
CPP_SRC += \
src/main.cpp \
src/key.cpp \
src/cert.cpp
Step 4: Install in Code**
#include <init.h>
#include <ssl.h>
extern const unsigned char comp_cert[];
extern const int comp_cert_len;
extern const unsigned char comp_key[];
extern const int comp_key_len;
void UserMain(void *pd)
{
int result = SSL_InstallCertificate(
comp_cert, comp_cert_len,
comp_key, comp_key_len
);
if (result == 0) {
printf("[OK] Certificate installed successfully\n");
} else {
printf("[ERR] Certificate installation failed: %d\n", result);
}
while (1) {
}
}
Installing Certificate Chain
For trusted certificates, install the full chain:
extern const unsigned char comp_device_cert[];
extern const int comp_device_cert_len;
extern const unsigned char comp_chain[];
extern const int comp_chain_len;
extern const unsigned char comp_key[];
extern const int comp_key_len;
void InstallWithChain() {
SSL_InstallCertificate(comp_chain, comp_chain_len,
comp_key, comp_key_len);
SSL_InstallCertificate(comp_device_cert, comp_device_cert_len,
comp_key, comp_key_len);
SSL_AddIntermediateCert(comp_chain, comp_chain_len);
}
Method 4: SSL Client Implementation
Connecting to secure servers with certificate validation.**
Basic SSL Client
#include <ssl.h>
#include <nettcp.h>
extern const char trustedCA[];
extern const int trustedCA_len;
void SecureClientConnection()
{
int fd =
connect(
"api.example.com", 443);
if (fd > 0) {
if (ssl) {
printf("[OK] Secure connection established\n");
const char* request = "GET / HTTP/1.1\r\n"
"Host: api.example.com\r\n"
"\r\n";
SSL_write(ssl, request, strlen(request));
char buffer[1024];
int n = SSL_read(ssl, buffer, sizeof(buffer)-1);
if (n > 0) {
buffer[n] = '\0';
printf("Response: %s\n", buffer);
}
SSL_close(ssl);
} else {
printf("[ERR] SSL handshake failed\n");
}
}
}
int close(int fd)
Close the specified file descriptor and free the associated resources.
Advanced: Certificate Verification
#include <ssl.h>
int VerifyCertCallback(int preverify_ok, WOLFSSL_X509_STORE_CTX* store) {
if (!preverify_ok) {
int err = X509_STORE_CTX_get_error(store);
int depth = X509_STORE_CTX_get_error_depth(store);
printf("Certificate verification failed at depth %d\n", depth);
printf("Error: %s\n", X509_verify_cert_error_string(err));
return 0;
}
return 1;
}
void SetupSecureClient() {
SSL_SetVerifyCallback(VerifyCertCallback);
SSL_SetVerifyMode(SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT);
}
Loading CAs from Storage
#include <effs_fat.h>
#include <ssl.h>
void LoadCAsFromSD() {
F_FILE* f =
f_open(
"ca-bundle.crt",
"r");
if (f) {
long size = f_tell(f);
char* certs = new char[size + 1];
certs[size] = '\0';
delete[] certs;
printf("[OK] Loaded CA certificates from SD\n");
}
}
#define f_read(buf, size, size_st, filehandle)
Read data from the current position in a file.
Definition api_f.h:526
#define f_seek(filehandle, offset, whence)
Move the stream position of an open file.
Definition api_f.h:550
#define f_close(filehandle)
Closes an opened file.
Definition api_f.h:487
#define f_open(filename, mode)
Opens a file in the file system.
Definition api_f.h:512
Troubleshooting
Common Browser Warning Messages
1. "Your Connection is Not Private"
┌────────────────────────────────────────┐
│ [!] Your connection is not private │
│ │
│ Attackers might be trying to steal │
│ your information... │
│ │
│ NET::ERR_CERT_AUTHORITY_INVALID │
└────────────────────────────────────────┘
Cause:** Certificate not signed by trusted CA
Solutions:**
- [OK] Use ACME for automatic trusted certificates
- [OK] Install your CA certificate on client devices
- [OK] Purchase certificate from public CA
- [!] For testing only: Click "Advanced" -> "Proceed (unsafe)"
2. "Certificate Name Mismatch"
┌────────────────────────────────────────┐
│ [!] Certificate doesn't match │
│ │
│ Certificate: device.example.com │
│ Accessing: 192.168.1.100 │
│ │
│ NET::ERR_CERT_COMMON_NAME_INVALID │
└────────────────────────────────────────┘
Cause:** Certificate issued for different name/IP
Solutions:**
- [OK] Access device using correct hostname
- [OK] Add Subject Alternative Names (SANs) to certificate
- [OK] Use wildcard certificate (*.example.com)
- [OK] Generate new certificate with correct CN/SAN
Example with multiple names:
void CertCallback(SslCertAttributes_t *attrs) {
attrs->commonName = "device.example.com";
attrs->altNames = "device.example.com,"
"device.local,"
"192.168.1.100,"
"10.0.0.50";
}
3. "Certificate Expired"
┌────────────────────────────────────────┐
│ [!] This certificate has expired │
│ │
│ Valid Until: Jan 15, 2025 │
│ Today: Feb 20, 2025 │
│ │
│ NET::ERR_CERT_DATE_INVALID │
└────────────────────────────────────────┘
Cause:** Certificate past expiration date
Solutions:**
- [OK] Use ACME for automatic renewal
- [OK] Enable auto-regeneration for self-signed certs
- [OK] Set calendar reminders for manual renewal
- [OK] Check device clock is synchronized (NTP)
4. "Certificate Not Yet Valid"
Cause:** Device clock incorrect or certificate future-dated
Solutions:**
#include <ntpclient.h>
void UserMain(void *pd) {
SetNTPServer("pool.ntp.org");
EnableNTP();
while (!NTPTimeSet()) {
}
printf("[OK] Time synchronized\n");
}
SSL Handshake Failures
Debugging Connection Issues
#include <ssl.h>
void DebugSSLConnection(const char* host, int port) {
printf("\n=== SSL Debug Info ===\n");
printf("Testing TCP connection to %s:%d...\n", host, port);
if (fd < 0) {
printf("[ERR] TCP connection failed\n");
return;
}
printf("[OK] TCP connected\n");
wolfSSL_Debugging_ON();
printf("Attempting SSL handshake...\n");
if (ssl) {
printf("[OK] SSL handshake successful\n");
WOLFSSL_CIPHER* cipher = SSL_get_current_cipher(ssl);
printf("Cipher: %s\n", SSL_CIPHER_get_name(cipher));
printf("Protocol: %s\n", SSL_get_version(ssl));
SSL_close(ssl);
} else {
printf("[ERR] SSL handshake failed\n");
int err = SSL_get_error(ssl, -1);
printf("Error code: %d\n", err);
}
wolfSSL_Debugging_OFF();
}
Common Error Codes
| Error | Meaning | Solution |
| -188 | ASN parse error | Certificate format invalid |
| -173 | Bad certificate | Corrupted or wrong cert format |
| -155 | No CA match | Add appropriate CA to trust list |
| -313 | Cipher suite mismatch | Update wolfSSL or adjust cipher list |
| -101 | Connection reset | Network issue or server rejected |
Certificate Verification Issues
Verification Flowchart
SSL Handshake Started
│
v
┌────────────────────┐
│ Verify Certificate │
└────────┬───────────┘
v
┌─────────┐
│ Trusted │ YES ┌─────────────────┐
│ CA? ├──────>│ Check Validity │
└────┬────┘ └────────┬────────┘
│ NO │
v v
┌────────┐ ┌──────────┐
│ Reject │ │ Check CN │
└────────┘ └─────┬────┘
v
┌─────────┐
│ Matches │ YES ┌─────────┐
│ Host? ├──────>│ Success │
└────┬────┘ └─────────┘
│ NO
v
┌────────┐
│ Reject │
└────────┘
Bypass Verification (Development Only!)
void InsecureClientSetup() {
SSL_SetVerifyMode(SSL_VERIFY_NONE);
printf("[!] Certificate verification DISABLED\n");
printf("[!] Use only for development/testing\n");
}
void SecureClientSetup() {
SSL_SetVerifyMode(SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT);
}
Memory and Resource Issues
Memory Requirements
Typical SSL Memory Usage:
| Component | Size |
| SSL Context | ~8-12 KB |
| Certificate Chain | 2-8 KB |
| Per Connection | 40-60 KB |
| Crypto Operations | 10-20 KB |
Minimum Recommended: 128 KB free heap Comfortable: 256 KB+ free heap
Checking Memory
#include <system.h>
void CheckMemoryForSSL() {
uint32_t freeHeap = FreeRTOSMemRemaining();
uint32_t minFree = FreeRTOSMemMinEver();
printf("\n=== Memory Status ===\n");
printf("Current Free: %lu KB\n", freeHeap / 1024);
printf("Minimum Ever: %lu KB\n", minFree / 1024);
if (freeHeap < 128 * 1024) {
printf("[!] WARNING: Low memory for SSL\n");
printf(" Consider: Reducing buffer sizes\n");
printf(" Limiting connections\n");
printf(" Using lighter ciphers\n");
} else {
printf("[OK] Sufficient memory for SSL\n");
}
}
Performance Optimization
Cipher Suite Selection
#include <ssl.h>
const char* fastCiphers =
"ECDHE-ECDSA-AES128-GCM-SHA256:"
"ECDHE-RSA-AES128-GCM-SHA256";
const char* balancedCiphers =
"ECDHE-ECDSA-AES256-GCM-SHA384:"
"ECDHE-ECDSA-AES128-GCM-SHA256:"
"ECDHE-RSA-AES256-GCM-SHA384";
const char* secureCiphers =
"ECDHE-ECDSA-CHACHA20-POLY1305:"
"ECDHE-ECDSA-AES256-GCM-SHA384";
void ConfigureCiphers() {
SSL_SetCipherList(balancedCiphers);
printf("Cipher list configured\n");
}
Connection Reuse
WOLFSSL_CTX* ctx = nullptr;
void InitSSLContext() {
if (!ctx) {
ctx = wolfSSL_CTX_new(wolfTLSv1_2_client_method());
}
}
WOLFSSL* CreateConnection(const char* host, int port) {
InitSSLContext();
if (fd < 0) return nullptr;
WOLFSSL* ssl = wolfSSL_new(ctx);
wolfSSL_set_fd(ssl, fd);
if (wolfSSL_connect(ssl) != SSL_SUCCESS) {
wolfSSL_free(ssl);
return nullptr;
}
return ssl;
}
Best Practices
Security Principles
1. Private Key Protection
┌─────────────────────────────────────────┐
│ Private Key Security Hierarchy │
├─────────────────────────────────────────┤
│ │
│ Most Secure: │
│ ├─ Hardware Security Module (HSM) │
│ ├─ Secure Enclave / TPM │
│ └─ Encrypted Storage │
│ │
│ Moderate: │
│ ├─ Compiled into firmware │
│ ├─ Flash storage with permissions │
│ └─ Protected file system │
│ │
│ Least Secure: │
│ ├─ Plain text on SD card │
│ ├─ Unprotected flash │
│ └─ Debug accessible memory │
│ │
└─────────────────────────────────────────┘
Best Practices:**
- [YES] Never store private keys in version control
- [YES] Use different keys for dev/test/production
- [YES] Rotate keys periodically
- [YES] Monitor for unauthorized access
- [NO] Don't log private keys
- [NO] Don't transmit private keys unencrypted
- [NO] Don't reuse keys across devices (except CA)
2. Certificate Validation
SSL_SetVerifyMode(SSL_VERIFY_NONE);
SSL_SetVerifyMode(SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT);
int VerifyCallback(int preverify, WOLFSSL_X509_STORE_CTX* store) {
return preverify && CustomSecurityChecks(store);
}
SSL_SetVerifyCallback(VerifyCallback);
3. Protocol and Cipher Configuration
SSL_SetMinVersion(SSL_3_0);
SSL_SetMinVersion(TLS_1_2);
SSL_SetMinVersion(TLS_1_3);
const char* strongCiphers =
"TLS_AES_256_GCM_SHA384:"
"TLS_CHACHA20_POLY1305_SHA256:"
"ECDHE-ECDSA-AES256-GCM-SHA384:"
"ECDHE-RSA-AES256-GCM-SHA384";
SSL_SetCipherList(strongCiphers);
Production Checklist
Pre-Deployment
[ ] Security Review:
[ ] All private keys properly protected
[ ] Certificate chain complete and valid
[ ] Strong cipher suites configured
[ ] Old protocols disabled (SSL, TLS 1.0/1.1)
[ ] Certificate validation enabled for clients
[ ] Certificate Management:
[ ] Expiration dates documented
[ ] Renewal process established
[ ] Contact information current
[ ] Backup certificates available
[ ] Monitoring Setup:
[ ] Certificate expiration alerts
[ ] Connection failure logging
[ ] Performance metrics
[ ] Security event logging
[ ] Testing Complete:
[ ] Browser compatibility verified
[ ] Client application tested
[ ] Load testing performed
[ ] Failover scenarios tested
[ ] Documentation:
[ ] Certificate inventory maintained
[ ] Configuration documented
[ ] Recovery procedures written
[ ] Contact list updated
Post-Deployment Monitoring
#include <ssl.h>
void MonitorSSLStatus() {
uint32_t activeConnections = SSL_GetActiveConnections();
uint32_t failedHandshakes = SSL_GetFailedHandshakes();
uint32_t certificateErrors = SSL_GetCertErrors();
printf("\n=== SSL Status ===\n");
printf("Active Connections: %lu\n", activeConnections);
printf("Failed Handshakes: %lu\n", failedHandshakes);
printf("Certificate Errors: %lu\n", certificateErrors);
uint32_t daysUntilExpiry = SSL_GetCertDaysRemaining();
if (daysUntilExpiry < 30) {
printf("[!] Certificate expires in %lu days!\n", daysUntilExpiry);
}
if (failedHandshakes > 100) {
printf("[!] High handshake failure rate!\n");
}
}
Development Workflow
Recommended Development Cycle
┌─────────────────────────────────────────┐
│ Development Stages │
├─────────────────────────────────────────┤
│ │
│ 1. Development (Local Network) │
│ └─> Self-Signed Certificates │
│ - Fast iteration │
│ - No external dependencies │
│ │
│ 2. Integration Testing │
│ └─> Private CA Certificates │
│ - Test certificate chains │
│ - Verify validation logic │
│ │
│ 3. Staging (Pre-Production) │
│ └─> ACME Staging Certs │
│ - Test automation │
│ - Verify renewal process │
│ │
│ 4. Production │
│ └─> ACME Production or Public CA │
│ - Trusted by all clients │
│ - Automatic renewal │
│ │
└─────────────────────────────────────────┘
Configuration Management
#ifdef DEVELOPMENT
#define SSL_MODE SSL_SELF_SIGNED
#define VERIFY_MODE SSL_VERIFY_NONE
#define DEBUG_SSL 1
#elif defined(STAGING)
#define SSL_MODE SSL_ACME_STAGING
#define VERIFY_MODE SSL_VERIFY_PEER
#define DEBUG_SSL 1
#elif defined(PRODUCTION)
#define SSL_MODE SSL_ACME_PRODUCTION
#define VERIFY_MODE SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT
#define DEBUG_SSL 0
#define ENABLE_SSL_MONITORING 1
#endif
void ConfigureSSL() {
#if SSL_MODE == SSL_SELF_SIGNED
#elif SSL_MODE == SSL_ACME_STAGING
AcmeConfig config;
config.acmeServer = ACME_LETSENCRYPT_STAGING;
StartAcmeHttps(config);
#elif SSL_MODE == SSL_ACME_PRODUCTION
AcmeConfig config;
config.acmeServer = ACME_LETSENCRYPT_PRODUCTION;
StartAcmeHttps(config);
#endif
SSL_SetVerifyMode(VERIFY_MODE);
#if DEBUG_SSL
wolfSSL_Debugging_ON();
#endif
}
Common Pitfalls to Avoid
1. Time Synchronization
void UserMain(void *pd) {
EnableNTP();
}
void UserMain(void *pd) {
EnableNTP();
SetNTPServer("pool.ntp.org");
uint32_t timeout = 0;
while (!NTPTimeSet() && timeout++ < 30) {
}
if (NTPTimeSet()) {
printf("[OK] Time synchronized\n");
} else {
printf("[!] Time sync failed, SSL may have issues\n");
}
}
2. Certificate Chain Issues
SSL_InstallCertificate(device_cert, device_cert_len,
device_key, device_key_len);
SSL_InstallCertificate(full_chain, full_chain_len,
device_key, device_key_len);
3. Resource Leaks
void MakeRequest() {
SSL_write(ssl, data, len);
}
void MakeRequest() {
if (fd < 0) return;
if (ssl) {
SSL_write(ssl, data, len);
SSL_close(ssl);
}
}
4. Hardcoded Credentials
#define CA_KEY "-----BEGIN PRIVATE KEY-----\nMIIE..."
#define DEVICE_PASSWORD "admin123"
extern const char comp_key[];
extern const int comp_key_len;
void LoadCredentials() {
ReadSecureKey(keyBuffer, sizeof(keyBuffer));
}
Additional Resources
NetBurner Examples
Located in your NNDK installation:
C:\nburn\examples\SSL\
+-- acmeservlet\ <- ACME automation
+-- SslOnboardCertGeneration\ <- Auto-generated certs
| +-- Simple\
| +-- Advanced\
| +-- CompiledCa\
+-- SslClientVerifyPeerBasic\ <- Client validation
+-- SslClientVerifyPeerEffs\ <- Loading CAs from storage
+-- CreateCerts\ <- Certificate generation scripts
+-- ECDSA\
+-- RSA\
Documentation and References
Official Documentation
Educational Resources
Books:**
Wikipedia Articles
Tools and Utilities
Certificate Management
- OpenSSL: Included in NNDK at
\Nburn\gcc\msys\1.0\bin\openssl.exe
- NetBurner CreateCerts: Scripts in
\nburn\CreateCerts\
- compfile: NetBurner utility to convert files to C++ arrays
Testing and Debugging
# Test SSL/TLS connection
openssl s_client -connect device.example.com:443 -showcerts
# Check certificate details
openssl x509 -in device.crt -text -noout
# Verify private key
openssl rsa -in device.key -check
# Test certificate chain
openssl verify -CAfile ca.crt device.crt
Online Testing
Quick Reference
Essential SSL Functions
StartAcmeHttps(config);
SSL_InstallCertificate(cert, key);
SSL_SetVerifyMode(mode);
SSL_GetCertDaysRemaining();
SSL_SetCertificateCallback(fn);
SSL_write(ssl, data, len);
SSL_read(ssl, buffer, size);
SSL_close(ssl);
wolfSSL_Debugging_ON();
SSL_get_error(ssl, ret);
CertGenReturnCode SSL_CreateNewSelfSignedCert(CertGenData &pGenData)
Generates a new self-signed certificate that will be stored on the device.
Configuration Constants
SSL_VERIFY_NONE
SSL_VERIFY_PEER
SSL_VERIFY_FAIL_IF_NO_PEER_CERT
SSL_3_0
TLS_1_0
TLS_1_1
TLS_1_2
TLS_1_3
ACME_LETSENCRYPT_STAGING
ACME_LETSENCRYPT_PRODUCTION
ACME_BUYPASS_PRODUCTION
SSL_FILETYPE_PEM
SSL_FILETYPE_DER
Recommended Approach for Most Users:**
- Development: Use auto-generated self-signed certificates
- Testing: Set up private CA for realistic testing
Production: Deploy ACME if possible, otherwise use public CA
Key Takeaways:**
- [LOCK] Private keys are your most sensitive security asset
- [SYNC] ACME automation eliminates manual certificate management
- [TIME] Time synchronization is critical for SSL/TLS
- [LINK] Complete certificate chains prevent trust issues
- [STAT] Monitor certificate expiration and connection health