ra8-firmware 0.1.0
Bare-metal firmware for the Renesas RA8 family (RA8D2 / RA8P1)
Loading...
Searching...
No Matches
ra8_rsip_internal.h File Reference

Cross-TU surface for the ra8_rsip driver split. More...

#include <stdint.h>
#include "ra8_attributes.h"
#include "ra8_err.h"
#include "ra8_rsip.h"
Include dependency graph for ra8_rsip_internal.h:
This graph shows which files directly or indirectly include this file:

Go to the source code of this file.

Enumerations

enum  ra8_rsip_intern_t : uint32_t {
  k_ra8_rsip_poll_budget = 4096UL ,
  k_ra8_rsip_word_shift = 2U ,
  k_ra8_rsip_byte_mask = 0xFFUL ,
  k_ra8_rsip_byte_bits = 8UL ,
  k_ra8_rsip_byte_shift_2 = 16UL ,
  k_ra8_rsip_byte_shift_3 = 24UL
}
 File-private constants used by the polling helpers and byte packing / unpacking math. More...
enum  ra8_rsip_intern2_t : uint32_t {
  k_ra8_rsip_kv_slot_max = 16UL ,
  k_ra8_rsip_kv_slot_w = 16UL ,
  k_ra8_rsip_iv_words = 4UL ,
  k_ra8_rsip_aead_iv_bytes = 12UL ,
  k_ra8_rsip_aes_block_w = 4UL
}
 Round-3 file-private constants. More...

Functions

ra8_err_t priv_wait_bit (ra8_rsip_off_t offset, uint32_t mask)
 Spin until mask is set in the register at offset.
ra8_err_t priv_hash_wait_done (void)
 Wait for the HASH engine to raise DONE after the trailing block.
uint32_t priv_pack_le (const uint8_t *p)
 Pack 4 little-endian bytes into a uint32_t.
void priv_unpack_le (uint32_t word, uint8_t *p)
 Unpack a uint32_t into 4 little-endian bytes.
void priv_push_bytes_to_port (ra8_rsip_off_t off, const uint8_t *in, uint32_t len)
 Stream a variable-length byte buffer into a single fixed MMIO port.
ra8_err_t priv_complete (uint32_t done_mask)
 Drive a single mailbox completion (DONE poll + ack).
uint32_t priv_handle_words_for (ra8_rsip_oem_cmd_t cmd)
 Map an OEM opcode to the wrapped-key body word count.
uint8_t priv_aes_alg_byte (uint32_t alg)
 Pick the AES algorithm byte that matches the wrapped key.
void priv_push_iv_lanes (ra8_rsip_off_t base, const uint8_t *iv, uint32_t iv_len)
 Push a bounded IV / nonce into 4 consecutive 32-bit lanes.
void priv_push_handle_body (const ra8_rsip_key_handle_t *handle)
 Stream a wrapped key body into the staging port.
void priv_load_handle (const ra8_rsip_key_handle_t *handle)
 Stream a wrapped-key body into the engine input FIFO.

Detailed Description

Cross-TU surface for the ra8_rsip driver split.

Tag
[Ring 3 / HAL] {World: S}

Not part of the public API. The RSIP-E50D HAL driver is split across three translation units by sub-responsibility:

  • ra8_rsip.c – core lifecycle, status / IRQ, TRNG, hardware SHA-256 one-shot, the software SHA-256 backend, SHA-256 / HMAC incremental contexts, and Software-Standby enter / exit;
  • ra8_rsip_cipher.c – the round-3 byte-packing primitives, the mailbox-completion driver, wrapped-key install, the symmetric AES cipher / AEAD path, ChaCha20 + Poly1305, and the generic hash / HMAC entry points;
  • ra8_rsip_asym.c – the generic multi-algorithm hash / HMAC entry points and the key-management surface (OEM anti-rollback counter, wrapped-key vault, key wrap / unwrap engine, key derivation, DOTF key routing), all fail-closed in production (no documented RSIP backend; Ch 52 fiction), plus the real HUM Ch 51 device-security paths (lifecycle / debug authorisation / tamper / side-channel arm) and the asymmetric byte-lane + handle-tail helpers shared with the ECC and RSA slices;
  • ra8_rsip_ecc.c – asymmetric ECDSA / ECDH / Ed25519 (fail-closed in production; no documented RSIP backend);
  • ra8_rsip_rsa.c – asymmetric RSA sign / verify and encrypt / decrypt (fail-closed in production; shares the asymmetric byte-lane helpers declared in ra8_rsip_asym_internal.h).

This header declares only the file-private constants and helper functions that are referenced by more than one of those TUs. Each symbol's full Doxygen contract lives at its single definition site; the declarations below are intentionally minimal. See CLAUDE.md "Test access to internal symbols (MC/DC scope)".

Since
0.1.0

Definition in file ra8_rsip_internal.h.

Enumeration Type Documentation

◆ ra8_rsip_intern2_t

enum ra8_rsip_intern2_t : uint32_t

Round-3 file-private constants.

Enumerator
k_ra8_rsip_kv_slot_max 

Number of vault slots.

k_ra8_rsip_kv_slot_w 

64-byte slot = 16 * uint32_t.

k_ra8_rsip_iv_words 

IV / nonce register lanes.

k_ra8_rsip_aead_iv_bytes 

Fixed GCM / CCM nonce length.

k_ra8_rsip_aes_block_w 

16-byte block = 4 * uint32_t.

Definition at line 74 of file ra8_rsip_internal.h.

◆ ra8_rsip_intern_t

enum ra8_rsip_intern_t : uint32_t

File-private constants used by the polling helpers and byte packing / unpacking math.

Enumerator
k_ra8_rsip_poll_budget 

Max iterations for any spin loop.

k_ra8_rsip_word_shift 

log2(sizeof(uint32_t)).

k_ra8_rsip_byte_mask 

Mask one byte out of a word.

k_ra8_rsip_byte_bits 

Shift one byte.

k_ra8_rsip_byte_shift_2 

Shift to high half of low word.

k_ra8_rsip_byte_shift_3 

Shift to top byte of word.

Definition at line 61 of file ra8_rsip_internal.h.

Function Documentation

◆ priv_aes_alg_byte()

uint8_t priv_aes_alg_byte ( uint32_t alg)

Pick the AES algorithm byte that matches the wrapped key.

Defined in ra8_rsip_cipher.c; shared with the key wrap / unwrap entry points in ra8_rsip_asym.c (KEK validation).

Parameters
[in]algWrapped-key install opcode (ra8_rsip_oem_cmd_t value).
Returns
AES algorithm selector byte, or 0 for a non-AES key.
Return values
0Key is not an AES key.
Precondition
alg is a ra8_rsip_oem_cmd_t value.
Caller treats 0 as "not an AES key".
Postcondition
No state modified.
Result selects the symmetric AES variant.
Note
Internal helper.
Since
0.1.0

Definition at line 204 of file ra8_rsip_cipher.c.

References k_ra8_rsip_oem_cmd_aes128, k_ra8_rsip_oem_cmd_aes192, k_ra8_rsip_oem_cmd_aes256, k_ra8_rsip_sym_alg_aes128, k_ra8_rsip_sym_alg_aes192, and k_ra8_rsip_sym_alg_aes256.

◆ priv_complete()

ra8_err_t priv_complete ( uint32_t done_mask)

Drive a single mailbox completion (DONE poll + ack).

Pre-asserts the DONE bit so the host fake spin terminates, waits on it, reads MBOX_RET (non-zero indicates an engine-side error), then W1C-acks the completion bit. Defined in ra8_rsip_cipher.c; shared with the asymmetric / key-management entry points in ra8_rsip_asym.c.

Parameters
[in]done_maskCompletion bit mask to poll and acknowledge.
Returns
k_ra8_ok on success; an error otherwise.
Return values
k_ra8_okOperation completed successfully.
k_ra8_err_hw_timeoutCompletion bit never observed.
k_ra8_err_hw_errorMBOX_RET was non-zero.
Precondition
A mailbox command has been issued.
done_mask is non-zero.
Postcondition
On k_ra8_ok, done_mask has been acknowledged.
On error, the engine result is reported to the caller.
Note
Internal helper.
Since
0.1.0

Definition at line 131 of file ra8_rsip_cipher.c.

References k_ra8_err_hw_error, k_ra8_ok, k_ra8_rsip_off_isr, k_ra8_rsip_off_mbox_ret, priv_wait_bit(), and ra8_rsip_reg32().

◆ priv_handle_words_for()

uint32_t priv_handle_words_for ( ra8_rsip_oem_cmd_t cmd)

Map an OEM opcode to the wrapped-key body word count.

Handle-body sizes mirror FSP r_rsip_key_injection.c. Defined in ra8_rsip_cipher.c; shared with the unwrap path in ra8_rsip_asym.c.

Parameters
[in]cmdOEM install / handle opcode.
Returns
Body word count, or 0 for an unsupported opcode.
Return values
0Unsupported / invalid opcode.
Precondition
cmd is one of ra8_rsip_oem_cmd_t.
Caller treats 0 as "unsupported".
Postcondition
No state modified.
Result is the wrapped-body length for cmd.
Note
Internal helper.
Since
0.1.0

Definition at line 83 of file ra8_rsip_cipher.c.

References k_ra8_rsip_handle_words_aes128, k_ra8_rsip_handle_words_aes192, k_ra8_rsip_handle_words_aes256, k_ra8_rsip_handle_words_chacha20, k_ra8_rsip_handle_words_ecc256_priv, k_ra8_rsip_handle_words_ecc384_priv, k_ra8_rsip_handle_words_ecc521_priv, k_ra8_rsip_handle_words_hmac_sha224, k_ra8_rsip_handle_words_hmac_sha256, k_ra8_rsip_handle_words_hmac_sha384, k_ra8_rsip_handle_words_hmac_sha512, k_ra8_rsip_handle_words_rsa2048_priv, k_ra8_rsip_handle_words_rsa3072_priv, k_ra8_rsip_handle_words_rsa4096_priv, k_ra8_rsip_oem_cmd_aes128, k_ra8_rsip_oem_cmd_aes128_xts, k_ra8_rsip_oem_cmd_aes192, k_ra8_rsip_oem_cmd_aes256, k_ra8_rsip_oem_cmd_aes256_xts, k_ra8_rsip_oem_cmd_chacha20, k_ra8_rsip_oem_cmd_ecc_brain256r1_priv, k_ra8_rsip_oem_cmd_ecc_brain384r1_priv, k_ra8_rsip_oem_cmd_ecc_brain512r1_priv, k_ra8_rsip_oem_cmd_ecc_ed25519_priv, k_ra8_rsip_oem_cmd_ecc_secp256k1_priv, k_ra8_rsip_oem_cmd_ecc_secp256r1_priv, k_ra8_rsip_oem_cmd_ecc_secp384r1_priv, k_ra8_rsip_oem_cmd_ecc_secp521r1_priv, k_ra8_rsip_oem_cmd_hmac_sha224, k_ra8_rsip_oem_cmd_hmac_sha256, k_ra8_rsip_oem_cmd_hmac_sha384, k_ra8_rsip_oem_cmd_hmac_sha512, k_ra8_rsip_oem_cmd_hmac_sha512_224, k_ra8_rsip_oem_cmd_hmac_sha512_256, k_ra8_rsip_oem_cmd_invalid, k_ra8_rsip_oem_cmd_rsa2048_priv, k_ra8_rsip_oem_cmd_rsa3072_priv, and k_ra8_rsip_oem_cmd_rsa4096_priv.

◆ priv_hash_wait_done()

ra8_err_t priv_hash_wait_done ( void )

Wait for the HASH engine to raise DONE after the trailing block.

On hardware the engine raises HASH_STATUS.DONE once it absorbs the trailing block + length. The bounded wait routes through the host ra8_fake_mmio seam inside priv_wait_bit (never forged by the driver). Defined in ra8_rsip.c; shared with the generic hash / HMAC path in ra8_rsip_cipher.c.

Returns
k_ra8_ok on success; k_ra8_err_hw_timeout otherwise.
Precondition
Engine is clocked and a hash command has been issued.
HASH_DATA_IN has received the full message body.
Postcondition
On k_ra8_ok, HASH_STATUS.DONE was observed set.
On timeout, no caller-visible state is modified.
Note
Internal helper; not exposed in the public header.
Since
0.1.0
Return values
k_ra8_okOperation completed successfully.
otherNon-zero error code from the underlying operation.

Definition at line 204 of file ra8_rsip.c.

References k_ra8_rsip_mask_isr_done, k_ra8_rsip_off_hash_status, and priv_wait_bit().

Referenced by ra8_rsip_sha256().

◆ priv_load_handle()

void priv_load_handle ( const ra8_rsip_key_handle_t * handle)

Stream a wrapped-key body into the engine input FIFO.

Publishes handle->alg to SYM_KEYH then streams the wrapped body via priv_push_handle_body. A NULL handle is a no-op. Defined in ra8_rsip_cipher.c; shared with every key-touching asymmetric entry point in ra8_rsip_asym.c.

Parameters
[in]handleSource handle, or NULL.
Precondition
Either handle is NULL or handle->body_words is valid.
The engine is idle and ready to latch a key handle.
Postcondition
On a non-NULL handle, SYM_KEYH carries handle->alg.
On a non-NULL handle, the body words have been streamed.
Note
Internal helper.
Since
0.1.0

Definition at line 194 of file ra8_rsip_cipher.c.

References ra8_rsip_key_handle_t::alg, k_ra8_rsip_off_sym_keyh, priv_push_handle_body(), and ra8_rsip_reg32().

◆ priv_pack_le()

uint32_t priv_pack_le ( const uint8_t * p)

Pack 4 little-endian bytes into a uint32_t.

Used by the RSIP register-port writers when streaming key material, IVs, and message blocks into the engine. Defined in ra8_rsip_cipher.c; shared with ra8_rsip.c and ra8_rsip_asym.c.

Parameters
[in]pSource byte pointer.
Returns
Packed little-endian 32-bit word.
Return values
valuePacked word built from p[0..3] in LE order.
Precondition
p is non-NULL and points to at least 4 readable bytes.
Caller has ensured p is correctly aligned for the architecture.
Postcondition
No caller-visible side effects beyond returning the packed word.
The 4 source bytes are unmodified.
Note
Internal helper.
Since
0.1.0

Definition at line 68 of file ra8_rsip_cipher.c.

References k_ra8_rsip_byte_bits, k_ra8_rsip_byte_shift_2, and k_ra8_rsip_byte_shift_3.

Referenced by priv_push_bytes_to_port().

◆ priv_push_bytes_to_port()

void priv_push_bytes_to_port ( ra8_rsip_off_t off,
const uint8_t * in,
uint32_t len )

Stream a variable-length byte buffer into a single fixed MMIO port.

Many RSIP sub-engines (HASH, KDF label / salt, AEAD AAD) accept their input through a single 32-bit register that latches one little-endian word per write. This helper packs whole 32-bit words via priv_pack_le and zero-pads any trailing 1 .. 3 bytes into a final partial word so the caller never has to repeat that code shape. Defined in ra8_rsip_cipher.c; shared with ra8_rsip.c and ra8_rsip_asym.c.

Parameters
[in]offRegister offset of the input port.
[in]inBuffer (>= len bytes); may be NULL only if len is 0.
[in]lenBytes to push (may be zero, in which case this is a no-op).
Precondition
off is a valid ra8_rsip_off_t mapping to a write-only FIFO.
Either len is zero or in is non-NULL.
Postcondition
The engine has observed ceil(len / 4) word writes to off.
No command-word side effect.
Note
Internal helper.
Since
0.1.0

Stream a variable-length byte buffer into a single fixed MMIO port.

Definition at line 150 of file ra8_rsip_cipher.c.

References k_ra8_rsip_byte_bits, k_ra8_rsip_trng_word_bytes, priv_pack_le(), and ra8_rsip_reg32().

◆ priv_push_handle_body()

void priv_push_handle_body ( const ra8_rsip_key_handle_t * handle)

Stream a wrapped key body into the staging port.

KEK loading for the wrap / unwrap engine and IKM loading for the KDF engine both push handle->body_words words into the same staging port. Defined in ra8_rsip_cipher.c; shared with the wrap and KDF paths in ra8_rsip_asym.c.

Parameters
[in]handleSource handle; never NULL here.
Precondition
handle is non-NULL.
handle->body_words <= length of handle->body.
Postcondition
KEY_STAGE has observed handle->body_words writes.
Caller is expected to have already published handle->alg to the appropriate algorithm-selector register.
Note
Internal helper.
Since
0.1.0

Stream a wrapped key body into the staging port.

Definition at line 187 of file ra8_rsip_cipher.c.

References ra8_rsip_key_handle_t::body, ra8_rsip_key_handle_t::body_words, k_ra8_rsip_off_key_stage, and ra8_rsip_reg32().

Referenced by priv_load_handle().

◆ priv_push_iv_lanes()

void priv_push_iv_lanes ( ra8_rsip_off_t base,
const uint8_t * iv,
uint32_t iv_len )

Push a bounded IV / nonce into 4 consecutive 32-bit lanes.

The RSIP exposes IV / nonce input as 4 consecutive 32-bit registers starting at base. The symmetric-cipher path uses SYM_IV0 and the key-wrap path uses KW_IV0; both share the layout. Bytes after iv_len are written as zero, so a 12-byte AEAD nonce never reads a nonexistent fourth source word. Defined in ra8_rsip_cipher.c and shared with the wrap engine in ra8_rsip_asym.c.

Parameters
[in]baseFirst lane offset (SYM_IV0 or KW_IV0).
[in]ivSource bytes; never NULL here.
[in]iv_lenSource length in bytes, at most 16.
Precondition
iv is non-NULL and addresses iv_len readable bytes.
base is the lane-0 offset of a 4-lane IV window.
Postcondition
Lanes 0..3 reflect the supplied IV in little-endian order with a zero-padded tail.
No command-word side effect.
Note
Internal helper.
Since
0.1.0

Push a bounded IV / nonce into 4 consecutive 32-bit lanes.

Definition at line 168 of file ra8_rsip_cipher.c.

References k_ra8_rsip_byte_bits, k_ra8_rsip_iv_words, k_ra8_rsip_trng_word_bytes, k_ra8_rsip_word_shift, and ra8_rsip_reg32().

◆ priv_unpack_le()

void priv_unpack_le ( uint32_t word,
uint8_t * p )

Unpack a uint32_t into 4 little-endian bytes.

Inverse of priv_pack_le. Used by the RSIP digest / key-output port readers to materialise byte buffers from the engine's word-addressed result registers. Defined in ra8_rsip_cipher.c; shared with ra8_rsip.c and ra8_rsip_asym.c.

Parameters
[in]wordLittle-endian 32-bit word to split.
[out]pDestination 4-byte buffer.
Precondition
p is non-NULL and points to at least 4 writable bytes.
Caller owns the destination buffer for the duration of the call.
Postcondition
p[0..3] reflect word in little-endian byte order.
No state outside the destination buffer is modified.
Note
Internal helper.
Since
0.1.0

Definition at line 75 of file ra8_rsip_cipher.c.

References k_ra8_rsip_byte_bits, k_ra8_rsip_byte_mask, k_ra8_rsip_byte_shift_2, and k_ra8_rsip_byte_shift_3.

◆ priv_wait_bit()

ra8_err_t priv_wait_bit ( ra8_rsip_off_t offset,
uint32_t mask )

Spin until mask is set in the register at offset.

Bounded busy-wait. NASA Power of 10 Rule 2 satisfied via a hard iteration cap (k_ra8_rsip_poll_budget). On the host unit-test build the poll routes through the ra8_fake_mmio wait seam (unarmed register = satisfied on the first poll; a test arms ra8_fake_mmio_fail_wait / ra8_fake_mmio_satisfy_after for the timeout / continuation legs). Defined in ra8_rsip.c; shared with the mailbox-completion driver in ra8_rsip_cipher.c.

Parameters
[in]offsetWord offset to poll.
[in]maskMask to AND against the read.
Returns
k_ra8_ok on success; k_ra8_err_hw_timeout otherwise.
Precondition
offset is one of the k_ra8_rsip_off_* values.
mask is non-zero.
Postcondition
On k_ra8_ok, (*reg & mask) == mask was observed.
On timeout, no caller-visible state is modified.
Note
Internal helper; not exposed in the public header.
Since
0.1.0
Return values
k_ra8_okOperation completed successfully.
otherNon-zero error code from the underlying operation.

Spin until mask is set in the register at offset.

Definition at line 120 of file ra8_rsip.c.

References k_ra8_err_hw_timeout, k_ra8_ok, k_ra8_rsip_poll_budget, and ra8_rsip_reg32().

Referenced by internal_run_bist(), priv_complete(), priv_hash_wait_done(), ra8_rsip_sha256(), and ra8_rsip_trng_read().