NetBurner 3.5.6
PDF Version
SSL/TLS and Certificates

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:

  1. Encryption: Data is scrambled so eavesdroppers see gibberish
  2. Authentication: Verify you're talking to the real server (not an attacker)
  3. 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:**

  1. Identity (Common Name/CN) - Who this certificate represents
  2. Public Key - Like an open padlock anyone can use to encrypt
  3. 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:**

// ACME with Let's Encrypt - Automatic trusted certificates
#include <acmeservlet.h>
void UserMain(void *pd) {
init();
// Configure ACME
AcmeConfig config;
config.domain = "mydevice.example.com";
config.email = "[email protected]";
// Automatic certificate issuance and renewal
StartAcmeHttps(config);
printf("Secure HTTPS server running\n");
while(1) { OSTimeDly(TICKS_PER_SECOND); }
}
#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:**

// Auto-generated self-signed certificate
#include <init.h>
#include <startnet.h>
void UserMain(void *pd) {
init();
// Automatically generates self-signed cert on first run
StartHttps(); // Port 443 by default
printf("HTTPS server running (self-signed)\n");
while(1) { OSTimeDly(TICKS_PER_SECOND); }
}
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>
// CA certificates you trust (example: Let's Encrypt root)
extern const char letsEncryptCA[];
extern const int letsEncryptCA_len;
void ConnectSecurely() {
// Initialize SSL system
// Add trusted CA certificates
SSL_AddCertToClientCaList(letsEncryptCA, letsEncryptCA_len);
// Create secure connection
int fd = connect("api.example.com", 443);
WOLFSSL* ssl = SSL_connect(fd);
if (ssl) {
SSL_write(ssl, "GET / HTTP/1.1\r\n\r\n", 18);
// ... read response ...
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:**

  • [YES] Development and testing
  • [YES] Single device, few users
  • [YES] Internal network only
  • [YES] Quick prototyping

    Limitations:**

  • [NO] Browser warnings for every user
  • [NO] Certificate must be manually installed on each client
  • [NO] No central management
  • [NO] Looks unprofessional in production

    NetBurner Implementation:**

    // Automatic - just enable HTTPS
    StartHttps(); // Self-signed cert auto-generated
    // Or manual control
    #define ENABLE_AUTOCERT_REGEN // In predef.h
    // Regenerates when expired (checked every minute by default)

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
// In your application
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) {
init();
// Install certificate before starting HTTPS
SSL_InstallCertificate(comp_cert, comp_cert_len,
comp_key, comp_key_len);
while(1) { OSTimeDly(TICKS_PER_SECOND); }
}

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:**

  1. 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
  2. Submit CSR to CA and complete verification
  3. Receive certificate and chain files
  4. Combine certificate with chain:
    # Create complete chain file
    cat device.crt intermediate.crt root.crt > device_chain.crt
  5. 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) {
init();
// Configure ACME settings
AcmeConfig config;
config.domain = "iot-device.example.com";
config.email = "[email protected]";
config.acmeServer = ACME_LETSENCRYPT_PRODUCTION;
// Start HTTPS with automatic ACME management
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);
}
while(1) { OSTimeDly(TICKS_PER_SECOND); }
}
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) {
init();
// Certificate automatically generated on first HTTPS connection
StartHttps(); // Default port 443
printf("HTTPS Server: %s\n", AppName);
printf("Certificate auto-generated if needed\n");
while (1) {
OSTimeDly(TICKS_PER_SECOND);
}
}

Advanced: Auto-Regeneration

Enable automatic regeneration when certificates expire:

// In your project's predef.h or compile flags:
#define ENABLE_AUTOCERT_REGEN
#define AUTO_CERT_GEN_CHECK (60 * 20) // Check every 20 minutes
// Default settings if not defined:
// - Checks every 1 minute
// - Certificate valid for 1 year
// - Uses SECP384R1 ECC by default

Customizing Certificate Generation

#include <ssl.h>
// Callback for custom certificate attributes
void CustomCertCallback(SslCertAttributes_t *attrs) {
// Set custom fields
attrs->country = "US";
attrs->state = "California";
attrs->locality = "San Diego";
attrs->organization = "My Company";
attrs->commonName = "mydevice.local";
// Add alternative names
attrs->altNames = "mydevice.local,192.168.1.100,#LOCAL";
// #LOCAL = automatically use mDNS .local name
}
void UserMain(void *pd) {
init();
// Register custom certificate callback
SSL_SetCertificateCallback(CustomCertCallback);
while(1) { OSTimeDly(TICKS_PER_SECOND); }
}

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) {
init();
// Ensure DNS is working (critical for ACME)
printf("Device IP: %s\n", GetIP().c_str());
printf("Waiting for DNS resolution...\n");
// Configure ACME
AcmeConfig config;
config.domain = "iot-device.example.com"; // Must match DNS
config.email = "[email protected]"; // For renewal notices
config.acmeServer = ACME_LETSENCRYPT_PRODUCTION;
config.acceptTerms = true;
// Optional: Use staging server for testing
// config.acmeServer = ACME_LETSENCRYPT_STAGING;
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) {
OSTimeDly(TICKS_PER_SECOND * 60);
// ACME renewal happens automatically in background
}
}

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>
// External declarations for compiled certificates
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)
{
init();
// Install certificate BEFORE starting HTTPS
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) {
OSTimeDly(TICKS_PER_SECOND);
}
}

Installing Certificate Chain

For trusted certificates, install the full chain:

// Combine certificate with intermediate and root CAs
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() {
// Method 1: Combined file (preferred)
SSL_InstallCertificate(comp_chain, comp_chain_len,
comp_key, comp_key_len);
// Method 2: Separate installation
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>
// CA certificate for validation
extern const char trustedCA[];
extern const int trustedCA_len;
void SecureClientConnection()
{
// Initialize SSL (once at startup)
// Add trusted CA certificates
SSL_AddCertToClientCaList(trustedCA, trustedCA_len);
// Create TCP connection
int fd = connect("api.example.com", 443);
if (fd > 0) {
// Upgrade to SSL
WOLFSSL* ssl = SSL_connect(fd);
if (ssl) {
printf("[OK] Secure connection established\n");
// Send data
const char* request = "GET / HTTP/1.1\r\n"
"Host: api.example.com\r\n"
"\r\n";
SSL_write(ssl, request, strlen(request));
// Read response
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");
}
close(fd);
}
}
int close(int fd)
Close the specified file descriptor and free the associated resources.

Advanced: Certificate Verification

#include <ssl.h>
// Custom verification callback
int VerifyCertCallback(int preverify_ok, WOLFSSL_X509_STORE_CTX* store) {
if (!preverify_ok) {
// Get error details
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));
// Decide whether to accept anyway
// return 1; // Accept despite error (insecure!)
return 0; // Reject connection (secure)
}
return 1; // Accept
}
void SetupSecureClient() {
// Add CA certificates
SSL_AddCertToClientCaList(trustedCA, trustedCA_len);
// Set verification callback
SSL_SetVerifyCallback(VerifyCertCallback);
// Set verification mode
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) {
// Get file size
f_seek(f, 0, SEEK_END);
long size = f_tell(f);
f_seek(f, 0, SEEK_SET);
// Read CA bundle
char* certs = new char[size + 1];
f_read(certs, 1, size, f);
certs[size] = '\0';
f_close(f);
// Add to trusted list
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) {
init();
// Synchronize time BEFORE SSL operations
SetNTPServer("pool.ntp.org");
EnableNTP();
// Wait for time sync
while (!NTPTimeSet()) {
OSTimeDly(TICKS_PER_SECOND);
}
printf("[OK] Time synchronized\n");
StartHttps(); // Now SSL will work
while(1) { OSTimeDly(TICKS_PER_SECOND); }
}

SSL Handshake Failures

Debugging Connection Issues

#include <ssl.h>
void DebugSSLConnection(const char* host, int port) {
printf("\n=== SSL Debug Info ===\n");
// 1. Test TCP connectivity
printf("Testing TCP connection to %s:%d...\n", host, port);
int fd = connect(host, port);
if (fd < 0) {
printf("[ERR] TCP connection failed\n");
return;
}
printf("[OK] TCP connected\n");
// 2. Enable SSL debugging
wolfSSL_Debugging_ON();
// 3. Attempt SSL handshake
printf("Attempting SSL handshake...\n");
WOLFSSL* ssl = SSL_connect(fd);
if (ssl) {
printf("[OK] SSL handshake successful\n");
// Get connection details
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);
}
close(fd);
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!)

// [!] WARNING: This is insecure! Only for development!
void InsecureClientSetup() {
// Disable certificate verification
SSL_SetVerifyMode(SSL_VERIFY_NONE);
printf("[!] Certificate verification DISABLED\n");
printf("[!] Use only for development/testing\n");
}
// For production, always verify:
void SecureClientSetup() {
SSL_AddCertToClientCaList(trustedCA, trustedCA_len);
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>
// Faster but less secure (use only if needed)
const char* fastCiphers =
"ECDHE-ECDSA-AES128-GCM-SHA256:"
"ECDHE-RSA-AES128-GCM-SHA256";
// Balanced (recommended)
const char* balancedCiphers =
"ECDHE-ECDSA-AES256-GCM-SHA384:"
"ECDHE-ECDSA-AES128-GCM-SHA256:"
"ECDHE-RSA-AES256-GCM-SHA384";
// Maximum security (slower)
const char* secureCiphers =
"ECDHE-ECDSA-CHACHA20-POLY1305:"
"ECDHE-ECDSA-AES256-GCM-SHA384";
void ConfigureCiphers() {
SSL_SetCipherList(balancedCiphers);
printf("Cipher list configured\n");
}

Connection Reuse

// Reuse SSL context for multiple connections
WOLFSSL_CTX* ctx = nullptr;
void InitSSLContext() {
if (!ctx) {
ctx = wolfSSL_CTX_new(wolfTLSv1_2_client_method());
SSL_AddCertToClientCaList(trustedCA, trustedCA_len);
}
}
WOLFSSL* CreateConnection(const char* host, int port) {
InitSSLContext(); // Only runs once
int fd = connect(host, port);
if (fd < 0) return nullptr;
WOLFSSL* ssl = wolfSSL_new(ctx);
wolfSSL_set_fd(ssl, fd);
if (wolfSSL_connect(ssl) != SSL_SUCCESS) {
wolfSSL_free(ssl);
close(fd);
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

// [X] BAD: Accepting any certificate
SSL_SetVerifyMode(SSL_VERIFY_NONE);
// [OK] GOOD: Proper validation
SSL_SetVerifyMode(SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT);
SSL_AddCertToClientCaList(trustedCA, trustedCA_len);
// [OK] BETTER: With custom verification
int VerifyCallback(int preverify, WOLFSSL_X509_STORE_CTX* store) {
// Additional checks: expiration, revocation, etc.
return preverify && CustomSecurityChecks(store);
}
SSL_SetVerifyCallback(VerifyCallback);

3. Protocol and Cipher Configuration

// [X] BAD: Allowing old protocols
SSL_SetMinVersion(SSL_3_0); // SSL is broken!
// [OK] GOOD: Modern protocols only
SSL_SetMinVersion(TLS_1_2);
// [OK] BETTER: Latest protocols
SSL_SetMinVersion(TLS_1_3);
// Configure strong cipher suites
const char* strongCiphers =
"TLS_AES_256_GCM_SHA384:" // TLS 1.3
"TLS_CHACHA20_POLY1305_SHA256:" // TLS 1.3
"ECDHE-ECDSA-AES256-GCM-SHA384:" // TLS 1.2
"ECDHE-RSA-AES256-GCM-SHA384"; // TLS 1.2
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>
// Monitor SSL health
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);
// Check certificate expiration
uint32_t daysUntilExpiry = SSL_GetCertDaysRemaining();
if (daysUntilExpiry < 30) {
printf("[!] Certificate expires in %lu days!\n", daysUntilExpiry);
// Trigger renewal process
}
// Alert if too many failures
if (failedHandshakes > 100) {
printf("[!] High handshake failure rate!\n");
// Send alert to administrator
}
}

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

// Use preprocessor for environment-specific config
#ifdef DEVELOPMENT
// Development: Self-signed, relaxed validation
#define SSL_MODE SSL_SELF_SIGNED
#define VERIFY_MODE SSL_VERIFY_NONE
#define DEBUG_SSL 1
#elif defined(STAGING)
// Staging: Test ACME, strict validation
#define SSL_MODE SSL_ACME_STAGING
#define VERIFY_MODE SSL_VERIFY_PEER
#define DEBUG_SSL 1
#elif defined(PRODUCTION)
// Production: Full security, monitoring
#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
StartHttps(); // Auto-generated cert
#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

// [X] BAD: Starting SSL before time sync
void UserMain(void *pd) {
init();
StartHttps(); // Certificates may appear expired!
EnableNTP(); // Too late!
}
// [OK] GOOD: Ensure time is synced first
void UserMain(void *pd) {
init();
EnableNTP();
SetNTPServer("pool.ntp.org");
// Wait for time sync
uint32_t timeout = 0;
while (!NTPTimeSet() && timeout++ < 30) {
OSTimeDly(TICKS_PER_SECOND);
}
if (NTPTimeSet()) {
printf("[OK] Time synchronized\n");
StartHttps(); // Now safe
} else {
printf("[!] Time sync failed, SSL may have issues\n");
}
}

2. Certificate Chain Issues

// [X] BAD: Installing only device certificate
SSL_InstallCertificate(device_cert, device_cert_len,
device_key, device_key_len);
// Clients may not trust the certificate!
// [OK] GOOD: Installing complete chain
// Combine: device cert + intermediate CA + root CA
SSL_InstallCertificate(full_chain, full_chain_len,
device_key, device_key_len);

3. Resource Leaks

// [X] BAD: Not cleaning up
void MakeRequest() {
WOLFSSL* ssl = SSL_connect(fd);
SSL_write(ssl, data, len);
// Forgot SSL_close() and close(fd)!
}
// [OK] GOOD: Proper cleanup
void MakeRequest() {
int fd = connect(host, port);
if (fd < 0) return;
WOLFSSL* ssl = SSL_connect(fd);
if (ssl) {
SSL_write(ssl, data, len);
SSL_close(ssl); // Free SSL resources
}
close(fd); // Close socket
}

4. Hardcoded Credentials

// [X] VERY BAD: Hardcoded in source
#define CA_KEY "-----BEGIN PRIVATE KEY-----\nMIIE..."
#define DEVICE_PASSWORD "admin123"
// [OK] BETTER: Compiled externally
extern const char comp_key[];
extern const int comp_key_len;
// [OK] BEST: Retrieved from secure storage
void LoadCredentials() {
// Read from encrypted flash, secure element, etc.
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

// Server Setup
StartHttps(); // Auto-generated cert
StartAcmeHttps(config); // ACME automation
SSL_InstallCertificate(cert, key); // Manual install
// Client Setup
SslInit(); // Initialize SSL
SSL_AddCertToClientCaList(ca); // Add trusted CA
SSL_connect(fd); // Secure connection
SSL_SetVerifyMode(mode); // Verification level
// Certificate Management
SSL_CreateNewSelfSignedCert(); // Generate cert
SSL_GetCertDaysRemaining(); // Check expiration
SSL_SetCertificateCallback(fn); // Custom attributes
// Data Transfer
SSL_write(ssl, data, len); // Send data
SSL_read(ssl, buffer, size); // Receive data
SSL_close(ssl); // Close connection
// Debugging
wolfSSL_Debugging_ON(); // Enable debug logs
SSL_get_error(ssl, ret); // Get error code
CertGenReturnCode SSL_CreateNewSelfSignedCert(CertGenData &pGenData)
Generates a new self-signed certificate that will be stored on the device.

Configuration Constants

// Verification Modes
SSL_VERIFY_NONE // No validation (insecure!)
SSL_VERIFY_PEER // Validate peer
SSL_VERIFY_FAIL_IF_NO_PEER_CERT // Require peer cert
// Protocol Versions
SSL_3_0 // Deprecated
TLS_1_0 // Deprecated
TLS_1_1 // Deprecated
TLS_1_2 // Minimum recommended
TLS_1_3 // Latest
// ACME Servers
ACME_LETSENCRYPT_STAGING // Testing
ACME_LETSENCRYPT_PRODUCTION // Production
ACME_BUYPASS_PRODUCTION // Alternative CA
// Certificate Types
SSL_FILETYPE_PEM // Text format
SSL_FILETYPE_DER // Binary format

Recommended Approach for Most Users:**

  1. Development: Use auto-generated self-signed certificates
  2. Testing: Set up private CA for realistic testing
  3. 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