AxlTls – TLS Support

Optional TLS 1.2 support using mbedTLS 3.6. Provides HTTPS server/client, self-signed certificate generation, and transparent TCP encryption.

Build requirement: make AXL_TLS=1 (adds ~200KB to the binary). Without this flag, all TLS functions return -1/NULL/false.

Header: <axl/axl-tls.h>

Overview

AXL’s TLS module wraps mbedTLS to provide:

  • Self-signed ECDSA P-256 certificate generation

  • TLS 1.2 server contexts (for HTTPS)

  • TLS 1.2 client contexts (for HTTPS GET/POST)

  • Transparent integration with AxlHttpServer and AxlHttpClient

HTTPS Server

Generate a certificate and enable TLS on the HTTP server:

#include <axl.h>

axl_tls_init();

// Generate self-signed cert (valid 10 years, ECDSA P-256)
void *cert, *key;
size_t cert_len, key_len;
axl_tls_generate_self_signed("MyServer", NULL, 0,
                             &cert, &cert_len, &key, &key_len);

// Create HTTPS server
AxlHttpServer *s = axl_http_server_new(8443);
axl_http_server_use_tls(s, cert, cert_len, key, key_len);
axl_http_server_add_route(s, "GET", "/", handler, NULL);

axl_free(cert);
axl_free(key);

axl_http_server_run(s);  // serves HTTPS

HTTPS Client

HTTPS is automatic – just use an https:// URL:

AXL_AUTOPTR(AxlHttpClient) c = axl_http_client_new();
AXL_AUTOPTR(AxlHttpClientResponse) resp = NULL;

// TLS handshake happens automatically
axl_http_get(c, "https://192.168.1.1:8443/api/status", &resp);

Certificate Generation

axl_tls_generate_self_signed creates an ECDSA P-256 certificate with SHA-256 signature:

  • Subject: CN=<name>,O=AximCode

  • Validity: current year to +10 years

  • SubjectAltName: DNS:localhost, IP:127.0.0.1, plus any provided IP addresses

  • Output: DER-encoded certificate and private key (caller frees)

Entropy

mbedTLS needs random numbers for key generation and TLS handshakes. AXL provides entropy via:

  1. EFI_RNG_PROTOCOL (hardware RNG) – preferred, used when available

  2. Software fallback – system time + monotonic counter mixing. A warning is logged when the fallback is used.

Security Considerations

  • Self-signed certificates are not trusted by browsers or standard TLS clients. Use curl --insecure or configure trust-on-first-use.

  • Certificate verification is disabled for client connections (MBEDTLS_SSL_VERIFY_NONE). This is appropriate for BMC/embedded use but not for public internet TLS.

  • The software entropy fallback is not cryptographically strong. For production use on hardware without an RNG, consider providing your own entropy source.

API Reference

Typedefs

typedef struct AxlTlsContext AxlTlsContext
typedef struct AxlTcp AxlTcp
typedef struct AxlLoop AxlLoop

Functions

bool axl_tls_available(void)

Check if TLS support was compiled in.

Returns:

true if AXL_TLS=1 was set at build time.

int axl_tls_init(void)

Initialize the TLS subsystem. Call once at startup.

Returns:

0 on success, -1 if TLS not compiled in or init failed.

void axl_tls_cleanup(void)

Shut down the TLS subsystem and free global resources.

int axl_tls_generate_self_signed(const char *cn, const AxlIPv4Address *ips, size_t ip_count, void **cert_der, size_t *cert_len, void **key_der, size_t *key_len)

Generate a self-signed ECDSA P-256 certificate.

The certificate includes SubjectAltName entries for localhost and any provided IP addresses. Valid for 10 years. Caller frees cert_der and key_der with axl_free().

Parameters:
  • cn – Common Name (e.g. “MyServer”)

  • ips – IP addresses for SAN (may be NULL)

  • ip_count – number of IP addresses

  • cert_der – [out] DER-encoded certificate

  • cert_len – [out] certificate length

  • key_der – [out] DER-encoded private key

  • key_len – [out] key length

Returns:

0 on success, -1 on failure.

int axl_tls_server_set_cert(const void *cert_der, size_t cert_len, const void *key_der, size_t key_len)

Load a server certificate and private key for TLS.

After this call, TLS accept operations use this certificate.

Parameters:
  • cert_der – DER-encoded certificate

  • cert_len – certificate length

  • key_der – DER-encoded private key

  • key_len – key length

Returns:

0 on success, -1 on failure.

AxlTlsContext *axl_tls_accept(AxlTcp *sock)

Create a TLS server context for an accepted TCP connection.

Wraps the socket for TLS. Call axl_tls_handshake() after to complete the TLS handshake.

Parameters:
  • sock – accepted TCP socket

Returns:

context, or NULL on failure.

AxlTlsContext *axl_tls_connect(AxlTcp *sock, const char *hostname)

Create a TLS client context for an outbound TCP connection.

hostname is used for SNI (Server Name Indication). Call axl_tls_handshake() after to complete the handshake.

Parameters:
  • sock – connected TCP socket

  • hostname – server hostname for SNI

Returns:

context, or NULL on failure.

int axl_tls_handshake(AxlTlsContext *ctx)

Perform or continue a TLS handshake.

May need to be called multiple times if data isn’t available yet.

Parameters:
  • ctx – TLS context

Returns:

0 on success (handshake complete), 1 if more data needed (call again after recv), -1 on error.

int axl_tls_read(AxlTlsContext *ctx, void *buf, size_t size, size_t *out_len)

Read decrypted data from a TLS connection.

Parameters:
  • ctx – TLS context

  • buf – output buffer

  • size – buffer capacity

  • out_len – [out] bytes read

Returns:

0 on success, -1 on error, 1 if more data needed.

int axl_tls_write(AxlTlsContext *ctx, const void *data, size_t len)

Write data over a TLS connection.

Encrypts and sends data via the underlying TCP socket.

Parameters:
  • ctx – TLS context

  • data – plaintext data

  • len – data length

Returns:

0 on success, -1 on error.

void axl_tls_stage_data(AxlTlsContext *ctx, const void *data, size_t len)

Stage received TCP data for TLS processing.

Points the TLS BIO recv callback at the provided buffer (zero-copy). Call before axl_tls_handshake() or axl_tls_read().

Parameters:
  • ctx – TLS context

  • data – received TCP data

  • len – data length

void axl_tls_free(AxlTlsContext *ctx)

Free a TLS context. Sends close_notify. NULL-safe.

Parameters:
  • ctx – context to free