|
ra8-firmware 0.1.0
Bare-metal firmware for the Renesas RA8 family (RA8D2 / RA8P1)
|
Implementation of the ra8_tls Mbed TLS facade. More...
#include "ra8_tls.h"#include <stddef.h>#include <stdint.h>#include <string.h>#include "ra8_attributes.h"#include "ra8_check.h"#include "ra8_err.h"#include "ra8_log.h"#include "mbedtls/error.h"#include "mbedtls/ssl.h"#include "mbedtls/x509_crt.h"#include "psa/crypto.h"Go to the source code of this file.
Data Structures | |
| struct | ra8_tls_session_handle |
| Forward declaration of the pool slot type. More... | |
Enumerations | |
| enum | tls_content_type_t : uint8_t { k_tls_content_handshake = 0x16U } |
| TLS record content type: Handshake (22). More... | |
Functions | |
| static bool | internal_handle_valid (const struct ra8_tls_session_handle *session) |
| Validate that a typed handle points into the static pool. | |
| static struct ra8_tls_session_handle * | internal_pool_acquire (void) |
| Locate the first free slot in the pool. | |
| static void | internal_pool_reset (void) |
| Reset every pool slot to a known-clean state. | |
| static void | internal_copy_cstr (char *dst, const char *src, size_t cap) |
| Bounded, always-NUL-terminating C-string copy. | |
| ra8_err_t | ra8_tls_global_init (void) |
| One-shot facade initialisation. | |
| ra8_err_t | ra8_tls_global_deinit (void) |
| Symmetric tear-down for ra8_tls_global_init. | |
| static ra8_err_t | internal_session_validate_args (ra8_tls_session_t *out_session, const ra8_tls_session_cfg_t *cfg) |
| Validate ra8_tls_session_open inputs before slot acquisition. | |
| static void | internal_apply_verify_cfg (struct ra8_tls_session_handle *slot, const ra8_tls_session_cfg_t *cfg) |
| Apply the caller's verify-mode and optional trust anchor to a slot. | |
| static ra8_err_t | internal_session_mbedtls_setup (struct ra8_tls_session_handle *slot, const ra8_tls_session_cfg_t *cfg) |
| Run the Mbed TLS init/config/setup sequence for a fresh slot. | |
| ra8_err_t | ra8_tls_session_open (ra8_tls_session_t *out_session, const ra8_tls_session_cfg_t *cfg) |
| Allocate a TLS session from the static pool. | |
| ra8_err_t | ra8_tls_session_close (ra8_tls_session_t session) |
| Release a TLS session back to the pool. | |
| ra8_err_t | ra8_tls_handshake (ra8_tls_session_t session) |
| Iterative TLS handshake driver. | |
| ra8_err_t | ra8_tls_send (ra8_tls_session_t session, const uint8_t *buf, size_t len, size_t *out_sent) |
| Encrypt and send application data. | |
| ra8_err_t | ra8_tls_recv (ra8_tls_session_t session, uint8_t *buf, size_t len, size_t *out_received) |
| Decrypt and receive application data. | |
| ra8_err_t | ra8_tls_get_cipher_suite (ra8_tls_session_t session, uint16_t *out_id, char *out_name, size_t name_cap) |
| Report the negotiated cipher suite for a session. | |
| ra8_err_t | ra8_tls_get_verify_result (ra8_tls_session_t session, uint32_t *out_flags) |
| Report the peer-certificate verification result for a session. | |
| ra8_err_t | ra8_tls_mss_clamp (uint16_t mtu, uint16_t *out_mss) |
| Compute the TCP MSS that keeps a segment inside one MTU frame. | |
Variables | |
| static const char *const | s_ra8_tls_tag = "ra8_tls" |
| Logging tag prefix used by every ra8_tls log line. | |
| static struct ra8_tls_session_handle | s_session_pool [k_ra8_tls_max_sessions] |
| Per-session state pool sized at compile time. | |
| static bool | s_initialized |
| One-shot global init flag protecting the PSA layer and pool state. | |
Implementation of the ra8_tls Mbed TLS facade.
Hosts the static session pool and the thin translation layer between Mbed TLS return codes and ra8_err_t. Randomness comes from the PSA crypto layer (Mbed TLS 4.x), which the application seeds through its mbedtls_psa_external_get_random hook.
Mbed TLS is only linked into the firmware build when RA8_USE_MBEDTLS=ON is set on the top-level CMake invocation. The host unit-test build (tests/CMakeLists.txt) defines RA8_OFF_TARGET for every translation unit and intentionally does not link the heavy Mbed TLS object library; in that mode this file replaces every mbedtls_ssl_* call with a tiny in-memory stand-in that exercises the BIO callback contract end-to-end. The public ra8_tls_* surface is identical in either build.
Definition in file ra8_tls.c.
| enum tls_content_type_t : uint8_t |
|
static |
Apply the caller's verify-mode and optional trust anchor to a slot.
Translates cfg->verify_mode into the matching Mbed TLS authentication mode and, when cfg->ca_pem is supplied, parses it into the slot's mbedtls_x509_crt and binds it as the CA chain. A parse failure is non-fatal here: the handshake still runs and reports the outcome through ra8_tls_get_verify_result (a required verify then simply fails). Hoisted out of internal_session_mbedtls_setup to keep that function within the NASA P10 Rule 4 line cap.
| [in,out] | slot | Pool slot whose config is being built. |
| [in] | cfg | Caller-supplied session configuration. |
Definition at line 332 of file ra8_tls.c.
References ra8_tls_session_handle::ca, ra8_tls_session_handle::cfg, ra8_tls_session_handle::config, k_ra8_tls_verify_default, k_ra8_tls_verify_none, k_ra8_tls_verify_optional, and k_ra8_tls_verify_required.
Referenced by internal_session_mbedtls_setup().
|
static |
Bounded, always-NUL-terminating C-string copy.
Copies at most cap - 1 bytes from src into dst and always writes a terminating NUL, so dst is a valid C string on return even when src is longer than the buffer (the tail is truncated). Used by ra8_tls_get_cipher_suite to hand back the cipher-suite name inside the caller's fixed buffer.
| [out] | dst | Destination buffer with room for cap bytes. |
| [in] | src | NUL-terminated source string. |
| [in] | cap | Capacity of dst in bytes; must be >= 1. |
Definition at line 206 of file ra8_tls.c.
Referenced by ra8_tls_get_cipher_suite().
|
static |
Validate that a typed handle points into the static pool.
Guards every public API against forged or NULL handles. The check is pointer-arithmetic-only so it stays branch-light at -O2.
| [in] | session | Handle to validate. |
| 0 | Success or default value. |
Definition at line 124 of file ra8_tls.c.
References ra8_tls_session_handle::in_use, k_ra8_tls_max_sessions, and s_session_pool.
Referenced by ra8_tls_get_cipher_suite(), ra8_tls_get_verify_result(), ra8_tls_handshake(), ra8_tls_recv(), ra8_tls_send(), and ra8_tls_session_close().
|
static |
Locate the first free slot in the pool.
< Nullptr.
Definition at line 143 of file ra8_tls.c.
References ra8_tls_session_handle::in_use, k_ra8_tls_max_sessions, and s_session_pool.
Referenced by ra8_tls_session_open().
|
static |
Reset every pool slot to a known-clean state.
Used by both global_init and global_deinit so the pool lifecycle is symmetric.
Definition at line 168 of file ra8_tls.c.
References ra8_tls_session_handle::ca, ra8_tls_session_handle::config, ra8_tls_session_handle::in_use, k_ra8_tls_max_sessions, memset(), s_session_pool, and ra8_tls_session_handle::ssl.
Referenced by ra8_tls_global_deinit(), and ra8_tls_global_init().
|
static |
Run the Mbed TLS init/config/setup sequence for a fresh slot.
On any sub-step failure the helper tears down the partial Mbed TLS state and zeroes the slot so the caller can return the error without leaking pool capacity. Hoisted out of ra8_tls_session_open to keep the orchestrator within the line cap.
| [in,out] | slot | Pool slot freshly marked in_use. |
| [in] | cfg | Caller-supplied session configuration. |
| k_ra8_ok | Slot fully configured. |
| k_ra8_err_hw_init_failed | Mbed TLS rejected one of the calls. |
Definition at line 388 of file ra8_tls.c.
References ra8_tls_session_handle::ca, ra8_tls_session_handle::cfg, ra8_tls_session_handle::config, internal_apply_verify_cfg(), k_ra8_err_hw_init_failed, k_ra8_ok, memset(), and ra8_tls_session_handle::ssl.
Referenced by ra8_tls_session_open().
|
static |
Validate ra8_tls_session_open inputs before slot acquisition.
Returns the same error codes as the inlined original so the public contract is preserved bit-for-bit; the helper exists purely to keep the open function within the NASA P10 Rule 4 line budget.
| [in,out] | out_session | Caller's session handle out-parameter. |
| [in] | cfg | Caller-supplied session configuration. |
| k_ra8_ok | Inputs valid. |
| k_ra8_err_invalid_arg | NULL out pointer / cfg / BIO callbacks. |
| k_ra8_err_not_initialized | Module has not been initialized. |
Definition at line 287 of file ra8_tls.c.
References ra8_tls_session_handle::cfg, k_ra8_err_invalid_arg, k_ra8_err_not_initialized, k_ra8_ok, and s_initialized.
Referenced by ra8_tls_session_open().
| ra8_err_t ra8_tls_get_cipher_suite | ( | ra8_tls_session_t | session, |
| uint16_t * | out_id, | ||
| char * | out_name, | ||
| size_t | name_cap ) |
Report the negotiated cipher suite for a session.
After a successful ra8_tls_handshake this returns the IANA cipher-suite name (e.g. TLS-ECDHE-RSA-WITH-AES-128-GCM-SHA256) and its 16-bit IANA identifier so an application can log exactly what was negotiated. In RA8_OFF_TARGET (host unit-test build) the handshake is a loopback drain rather than a real negotiation, so a deterministic sentinel is reported: out_name becomes "off-target-loopback" and *out_id becomes 0. The output name is always NUL-terminated and never exceeds name_cap bytes.
| [in] | session | Open session handle in the application-data state. |
| [out] | out_id | Receives the 16-bit IANA cipher-suite id (0 when unknown / fake). |
| [out] | out_name | Receives the NUL-terminated cipher-suite name. Truncated to fit when the real name is longer. |
| [in] | name_cap | Capacity of out_name in bytes; must be >= 1. |
| k_ra8_ok | Cipher reported into the outputs. |
| k_ra8_err_invalid_arg | Any pointer NULL, name_cap zero, or session invalid. |
| k_ra8_err_not_initialized | Module not initialized. |
Definition at line 600 of file ra8_tls.c.
References internal_copy_cstr(), internal_handle_valid(), k_ra8_err_invalid_arg, k_ra8_err_not_initialized, k_ra8_ok, s_initialized, and ra8_tls_session_handle::ssl.
Referenced by demo_report().
| ra8_err_t ra8_tls_get_verify_result | ( | ra8_tls_session_t | session, |
| uint32_t * | out_flags ) |
Report the peer-certificate verification result for a session.
Wraps mbedtls_ssl_get_verify_result: 0 means the peer chain satisfied the configured verify_mode; any non-zero value is the OR of MBEDTLS_X509_BADCERT_* / MBEDTLS_X509_BADCRL_* flags. In RA8_OFF_TARGET the loopback path reports 0 (verified).
| [in] | session | Open session handle in the application-data state. |
| [out] | out_flags | Receives the verification bit set (0 == OK). |
| k_ra8_ok | Result written to *out_flags. |
| k_ra8_err_invalid_arg | out_flags NULL or session invalid. |
| k_ra8_err_not_initialized | Module not initialized. |
Definition at line 631 of file ra8_tls.c.
References internal_handle_valid(), k_ra8_err_invalid_arg, k_ra8_err_not_initialized, k_ra8_ok, s_initialized, and ra8_tls_session_handle::ssl.
Referenced by demo_report().
| ra8_err_t ra8_tls_global_deinit | ( | void | ) |
Symmetric tear-down for ra8_tls_global_init.
Frees every still-open session, wipes the CTR_DRBG state, and marks the module uninitialized so a subsequent ra8_tls_global_init succeeds again.
| k_ra8_ok | Facade torn down. |
| k_ra8_err_not_initialized | ra8_tls_global_init was never called. |
Definition at line 249 of file ra8_tls.c.
References internal_pool_reset(), k_ra8_err_not_initialized, k_ra8_ok, and s_initialized.
Referenced by demo_run_tls().
| ra8_err_t ra8_tls_global_init | ( | void | ) |
One-shot facade initialisation.
Brings the PSA crypto layer online and marks the session pool empty. Mbed TLS 4.x sources randomness from PSA (psa_generate_random) rather than a facade-owned CTR_DRBG, so the actual entropy is drawn lazily on the first random call through the application-supplied mbedtls_psa_external_get_random hook (the RSIP TRNG on hardware). Safe to call exactly once per boot; subsequent calls without a matching ra8_tls_global_deinit return k_ra8_err_exists.
Algorithm:
| k_ra8_ok | Facade ready. |
| k_ra8_err_exists | Already initialized this boot. |
| k_ra8_err_hw_error | psa_crypto_init failed. |
Definition at line 222 of file ra8_tls.c.
References internal_pool_reset(), k_ra8_err_exists, k_ra8_err_hw_error, k_ra8_ok, ra8_log_error, ra8_log_info, ra8_log_warn, s_initialized, and s_ra8_tls_tag.
Referenced by demo_run_tls().
| ra8_err_t ra8_tls_handshake | ( | ra8_tls_session_t | session | ) |
Iterative TLS handshake driver.
Wraps mbedtls_ssl_handshake and translates its return value into an ra8_err_t. Returns k_ra8_err_would_block while the underlying BIO is non-blocking and waiting for I/O so the caller can loop without consuming the entire transport-level event budget.
In RA8_OFF_TARGET (host unit-test build) the call short- circuits to k_ra8_ok after a single BIO drain so the loopback test path can complete without a real cryptographic handshake.
| [in,out] | session | Open session handle. |
| k_ra8_ok | Handshake complete. |
| k_ra8_err_invalid_arg | session invalid. |
| k_ra8_err_not_initialized | Module not initialized. |
| k_ra8_err_would_block | BIO is non-blocking; retry later. |
| k_ra8_err_comm_error | Mbed TLS reported a fatal handshake failure (cert / protocol / decode). |
Definition at line 479 of file ra8_tls.c.
References ra8_tls_session_handle::cfg, internal_handle_valid(), k_ra8_err_comm_error, k_ra8_err_invalid_arg, k_ra8_err_not_initialized, k_ra8_err_would_block, k_ra8_ok, k_tls_content_handshake, ra8_log_error, s_initialized, s_ra8_tls_tag, and ra8_tls_session_handle::ssl.
Referenced by demo_handshake().
| ra8_err_t ra8_tls_mss_clamp | ( | uint16_t | mtu, |
| uint16_t * | out_mss ) |
Compute the TCP MSS that keeps a segment inside one MTU frame.
Pure arithmetic helper for TLS-over-TCP clients on the #21-pinned 128-byte MTU link: subtracts the fixed IPv4 + TCP header overhead from mtu to yield the largest TCP payload (Maximum Segment Size) that still fits one Ethernet frame the ESWM egress transmits cleanly. The result is what a caller feeds to the transport (e.g. an Mbed TLS maximum-fragment-length hint or a NetX Duo socket MSS) so the TLS record layer never asks the MAC to send an over-length frame.
| [in] | mtu | Link MTU in bytes (payload, excluding the 14-byte Ethernet header); must be >= k_ra8_tls_mtu_min. |
| [out] | out_mss | Receives the clamped MSS (mtu - IPv4 - TCP) in bytes. |
| k_ra8_ok | MSS written to *out_mss. |
| k_ra8_err_invalid_arg | out_mss NULL, or mtu too small to leave at least k_ra8_tls_mss_min bytes. |
mtu leaves room for a >= k_ra8_tls_mss_min byte segment. Definition at line 651 of file ra8_tls.c.
References k_ra8_err_invalid_arg, k_ra8_ok, k_ra8_tls_ipv4_hdr_bytes, k_ra8_tls_mss_min, and k_ra8_tls_tcp_hdr_bytes.
Referenced by demo_run_tls().
| ra8_err_t ra8_tls_recv | ( | ra8_tls_session_t | session, |
| uint8_t * | buf, | ||
| size_t | len, | ||
| size_t * | out_received ) |
Decrypt and receive application data.
Wraps mbedtls_ssl_read. *out_received == 0 together with k_ra8_ok denotes a clean peer close-notify; k_ra8_err_would_block means the underlying transport had no data ready.
| [in,out] | session | Open session handle in the application-data state. |
| [out] | buf | Plaintext output buffer. |
| [in] | len | Capacity of buf in bytes. |
| [out] | out_received | Bytes decrypted into buf. |
| k_ra8_ok | Decrypted *out_received bytes (0 on clean close). |
| k_ra8_err_invalid_arg | Any pointer NULL or session invalid. |
| k_ra8_err_not_initialized | Module not initialized. |
| k_ra8_err_would_block | No ciphertext available yet. |
| k_ra8_err_comm_error | Fatal TLS-layer error. |
Definition at line 557 of file ra8_tls.c.
References ra8_tls_session_handle::cfg, internal_handle_valid(), k_ra8_err_comm_error, k_ra8_err_invalid_arg, k_ra8_err_not_initialized, k_ra8_err_would_block, k_ra8_ok, s_initialized, and ra8_tls_session_handle::ssl.
Referenced by demo_exchange().
| ra8_err_t ra8_tls_send | ( | ra8_tls_session_t | session, |
| const uint8_t * | buf, | ||
| size_t | len, | ||
| size_t * | out_sent ) |
Encrypt and send application data.
Wraps mbedtls_ssl_write. Returns the number of bytes accepted by the TLS layer through out_sent; partial writes are reported back to the caller so they can advance their buffer pointer.
| [in,out] | session | Open session handle in the application-data state. |
| [in] | buf | Plaintext input buffer. |
| [in] | len | Number of bytes to send (0 is a no-op). |
| [out] | out_sent | Bytes consumed by the TLS layer (always <= len). |
| k_ra8_ok | Wrote *out_sent bytes. |
| k_ra8_err_invalid_arg | Any pointer NULL or session invalid. |
| k_ra8_err_not_initialized | Module not initialized. |
| k_ra8_err_would_block | Non-blocking BIO returned WANT_WRITE. |
| k_ra8_err_comm_error | Fatal TLS-layer error. |
Definition at line 517 of file ra8_tls.c.
References ra8_tls_session_handle::cfg, internal_handle_valid(), k_ra8_err_comm_error, k_ra8_err_invalid_arg, k_ra8_err_not_initialized, k_ra8_err_would_block, k_ra8_ok, s_initialized, and ra8_tls_session_handle::ssl.
Referenced by demo_exchange().
| ra8_err_t ra8_tls_session_close | ( | ra8_tls_session_t | session | ) |
Release a TLS session back to the pool.
Validates that session actually points into the pool, runs mbedtls_ssl_free / mbedtls_ssl_config_free on the slot, and clears the in-use bit. Safe to call on any open session, even one that has not completed its handshake.
| [in,out] | session | Handle previously returned by ra8_tls_session_open. |
| k_ra8_ok | Slot released. |
| k_ra8_err_invalid_arg | session is NULL or does not point into the pool. |
| k_ra8_err_not_initialized | ra8_tls_global_init was never called. |
Definition at line 461 of file ra8_tls.c.
References ra8_tls_session_handle::ca, ra8_tls_session_handle::config, internal_handle_valid(), k_ra8_err_invalid_arg, k_ra8_err_not_initialized, k_ra8_ok, memset(), s_initialized, and ra8_tls_session_handle::ssl.
Referenced by demo_run_tls().
| ra8_err_t ra8_tls_session_open | ( | ra8_tls_session_t * | out_session, |
| const ra8_tls_session_cfg_t * | cfg ) |
Allocate a TLS session from the static pool.
Searches the in-use bitmap for a free slot, copies cfg into the slot, runs mbedtls_ssl_setup / mbedtls_ssl_set_bio and returns the typed pointer through out_session.
| [out] | out_session | Receives the new opaque handle on success. Set to NULL on any non-success return. |
| [in] | cfg | Session configuration; both BIO callbacks must be non-NULL. The struct itself is copied; the caller may free it on return. |
| k_ra8_ok | Session allocated and ready for handshake. |
| k_ra8_err_invalid_arg | out_session or cfg is NULL, or one of the BIO callbacks is NULL. |
| k_ra8_err_not_initialized | ra8_tls_global_init was never called. |
| k_ra8_err_no_mem | Pool exhausted (more than k_ra8_tls_max_sessions open). |
Definition at line 432 of file ra8_tls.c.
References ra8_tls_session_handle::cfg, ra8_tls_session_handle::in_use, internal_pool_acquire(), internal_session_mbedtls_setup(), internal_session_validate_args(), k_ra8_err_no_mem, k_ra8_ok, ra8_log_warn, and s_ra8_tls_tag.
Referenced by demo_run_tls().
|
static |
|
static |
Logging tag prefix used by every ra8_tls log line.
Definition at line 61 of file ra8_tls.c.
Referenced by ra8_tls_global_init(), ra8_tls_handshake(), and ra8_tls_session_open().
|
static |
Per-session state pool sized at compile time.
Definition at line 94 of file ra8_tls.c.
Referenced by internal_handle_valid(), internal_pool_acquire(), and internal_pool_reset().