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

RSIP-E50D hash / HMAC + key-management (fail-closed). More...

#include <stdint.h>
#include "ra8_attributes.h"
#include "ra8_check.h"
#include "ra8_err.h"
#include "ra8_log.h"
#include "ra8_rsip.h"
#include "ra8_rsip_asym_internal.h"
#include "ra8_rsip_internal.h"
#include "ra8_rsip_regs.h"
Include dependency graph for ra8_rsip_asym.c:

Go to the source code of this file.

Functions

ra8_err_t ra8_rsip_hash (ra8_rsip_hash_alg_t alg, const uint8_t *msg, uint32_t msg_len, uint8_t *digest, uint32_t digest_len)
 Compute a hash of an in-memory buffer using the selected algorithm.
ra8_err_t ra8_rsip_hmac (const ra8_rsip_key_handle_t *key, const uint8_t *msg, uint32_t msg_len, uint8_t *mac, uint32_t mac_len)
 HMAC-SHA-2 / HMAC-SHA-3 over a buffer using a wrapped key.
ra8_err_t ra8_rsip_oem_bl_version_get (uint32_t *out)
 Read the latched OEM boot loader version counter.
ra8_err_t ra8_rsip_oem_bl_version_increment (void)
 Increment the OEM boot loader version (anti-rollback step).
ra8_err_t ra8_rsip_oem_bl_version_lock (void)
 Latch the OEM_BL_LOCK so further increments are rejected.
ra8_err_t ra8_rsip_kv_read (uint8_t slot, uint8_t *out)
 Read a wrapped-key blob from a vault slot.
ra8_err_t ra8_rsip_kv_write (uint8_t slot, const uint8_t *in)
 Write a wrapped-key blob into a vault slot.
ra8_err_t ra8_rsip_kv_erase (uint8_t slot)
 Zeroise a vault slot.
ra8_err_t ra8_rsip_kv_count (uint32_t *out)
 Snapshot the populated-slot count.
ra8_err_t ra8_rsip_key_wrap (const ra8_rsip_key_handle_t *kek, const uint8_t *iv, const ra8_rsip_key_handle_t *src, uint8_t *blob)
 Wrap a key handle into a transportable blob using a KEK.
ra8_err_t ra8_rsip_key_unwrap (const ra8_rsip_key_handle_t *kek, const uint8_t *iv, const uint8_t *blob, ra8_rsip_key_handle_t *dest)
 Unwrap a transportable blob into a key handle.
ra8_err_t ra8_rsip_kdf (ra8_rsip_kdf_op_t op, const ra8_rsip_key_handle_t *ikm, const uint8_t *label, uint32_t label_len, const uint8_t *salt, uint32_t salt_len, uint32_t out_len, ra8_rsip_key_handle_t *out)
 Derive a key from input keying material + label/salt/info.
ra8_err_t ra8_rsip_dotf_route (uint8_t which, uint8_t slot, bool on)
 Route a wrapped-key vault slot to one of the DOTF instances.

Variables

static const char * s_tag = "RSIP"
 Logger tag used by every ra8_log_* call in this TU.

Detailed Description

RSIP-E50D hash / HMAC + key-management (fail-closed).

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

Hash / HMAC + key-management slice of the RA8D2 RSIP-E50D HAL driver, split out of ra8_rsip.c to keep every translation unit under the file-size budget.

The generic multi-algorithm hash family (SHA-2 / SHA-3 / SHAKE) + HMAC and the whole key-management surface – the OEM boot-loader anti-rollback counter, the wrapped-key vault, the KEK-backed key wrap / unwrap engine, HKDF / HUK / UID key derivation, and DOTF key delivery routing – are FAIL-CLOSED in production. HUM Ch 52 "Renesas Secure IP (RSIP-E50D)" is a six-page feature overview (p 3302-3307) with no hash / key command-register map, so the HUM Ch 52.1 / 52.2.3 citations that used to sit on those register pokes were fabricated (they passed cite_check while being false, exactly the #214 / #181 finding). The off-target-only command path is gated behind the stub-crypto guard and a production build returns k_ra8_err_not_supported – never a plausible-looking wrong digest, MAC, wrapped key, or derived key. The only real hash path on this part is ra8_rsip_sha256 -> the software SHA-256 backend in ra8_rsip.c (proven in rsip_sha256_kat); it is untouched. Any real hash / HMAC / KDF need is served by tf-psa-crypto on the M85 (silicon-proven in psa_crypto_hil), issue #215.

The device-security paths (device lifecycle, the three debug-authorisation levels, the tamper subsystem, and the SPA / DPA side-channel arm) were split out into ra8_rsip_devsec.c and fail-closed the same way (issue #216): they drove an invented "RSIP security-state" register block cited to HUM Ch 51, which is a prose feature index with no register map.

Cross-TU primitives shared with ra8_rsip.c and ra8_rsip_cipher.c are declared in ra8_rsip_internal.h. The asymmetric byte-lane (internal_asym_push / internal_asym_pull) + handle-tail (internal_zero_handle_tail) helpers shared with ra8_rsip_rsa.c / ra8_rsip_ecc.c are declared in ra8_rsip_asym_internal.h and defined below; because every consumer references them only from inside its own stub-crypto guard, they too live inside the guard here and are absent from a production image.

Since
0.1.0

Definition in file ra8_rsip_asym.c.

Function Documentation

◆ ra8_rsip_dotf_route()

ra8_err_t ra8_rsip_dotf_route ( uint8_t which,
uint8_t slot,
bool on )
nodiscard

Route a wrapped-key vault slot to one of the DOTF instances.

Parameters
[in]whichDOTF instance (0 or 1).
[in]slotVault slot to feed (must contain an AES key).
[in]ontrue to enable the route, false to disable.
Returns
ra8_err_t error code.
Return values
k_ra8_okRoute applied.
k_ra8_err_invalid_argwhich not 0/1 or slot out of range.
Precondition
which < 2.
If on is true, slot < k_ra8_rsip_kv_slot_count.
Postcondition
DOTFn_CTRL reflects the requested route.
Note
Thread safety: not thread-safe.
Since
0.1.0

Definition at line 747 of file ra8_rsip_asym.c.

References k_ra8_err_not_supported.

◆ ra8_rsip_hash()

ra8_err_t ra8_rsip_hash ( ra8_rsip_hash_alg_t alg,
const uint8_t * msg,
uint32_t msg_len,
uint8_t * digest,
uint32_t digest_len )
nodiscard

Compute a hash of an in-memory buffer using the selected algorithm.

Generalisation of ra8_rsip_sha256 to every algorithm in ra8_rsip_hash_alg_t. out_len must be at least the digest size for the selected algorithm; for SHAKE-128/256 out_len is the requested XOF length and may be any positive value.

Parameters
[in]algAlgorithm selector.
[in]msgMessage to hash; may be NULL only if msg_len is zero.
[in]msg_lenMessage length in bytes.
[out]digestOutput buffer.
[in]digest_lenOutput buffer length.
Returns
ra8_err_t error code.
Return values
k_ra8_okDigest written.
k_ra8_err_null_ptrdigest was NULL, or msg was NULL with non-zero msg_len.
k_ra8_err_invalid_argdigest_len too small for alg.
k_ra8_err_hw_timeoutEngine never signalled DONE.
Precondition
alg is one of k_ra8_rsip_hash_*.
If msg_len > 0, msg is non-NULL.
Postcondition
On success, digest[0..N-1] is the digest where N is the algorithm's natural output size (or digest_len for SHAKE).
HASH_STATUS.DONE has been acked.
Note
Thread safety: not thread-safe.
See also
ra8_rsip_sha256
Since
0.1.0

Definition at line 633 of file ra8_rsip_asym.c.

References k_ra8_err_not_supported, RA8_CHECK_NULL_PTR, and s_tag.

◆ ra8_rsip_hmac()

ra8_err_t ra8_rsip_hmac ( const ra8_rsip_key_handle_t * key,
const uint8_t * msg,
uint32_t msg_len,
uint8_t * mac,
uint32_t mac_len )
nodiscard

HMAC-SHA-2 / HMAC-SHA-3 over a buffer using a wrapped key.

Parameters
[in]keyWrapped HMAC key handle.
[in]msgBuffer to authenticate.
[in]msg_lenLength of msg in bytes.
[out]macOutput MAC buffer (>= digest size of HMAC's underlying hash).
[in]mac_lenmac buffer length.
Returns
ra8_err_t error code.
Return values
k_ra8_okMAC written.
k_ra8_err_null_ptrAny required pointer was NULL.
k_ra8_err_invalid_argmac_len too small for the algo.
k_ra8_err_hw_timeoutEngine never signalled DONE.
Precondition
key->alg is a HMAC opcode.
mac is non-NULL.
Postcondition
On success, mac[0..N-1] is the HMAC.
Note
Thread safety: not thread-safe.
Since
0.1.0

Definition at line 647 of file ra8_rsip_asym.c.

References k_ra8_err_not_supported, RA8_CHECK_NULL_PTR, and s_tag.

◆ ra8_rsip_kdf()

ra8_err_t ra8_rsip_kdf ( ra8_rsip_kdf_op_t op,
const ra8_rsip_key_handle_t * ikm,
const uint8_t * label,
uint32_t label_len,
const uint8_t * salt,
uint32_t salt_len,
uint32_t out_len,
ra8_rsip_key_handle_t * out )
nodiscard

Derive a key from input keying material + label/salt/info.

Implements:

  • HKDF-SHA-256 / 384 / 512 – op selects the hash flavour; ikm is consumed as the IKM.
  • HUK / UID bound – op selects the source root, ikm is NULL, and the engine binds the device-unique value.
Parameters
[in]opKDF mode selector.
[in]ikmInput keying material handle (may be NULL for HUK / UID modes).
[in]labelLabel / context bytes.
[in]label_lenLabel length in bytes.
[in]saltSalt bytes (may be NULL).
[in]salt_lenSalt length in bytes.
[in]out_lenBytes of derived material requested.
[out]outWrapped derived-key handle.
Returns
ra8_err_t error code.
Return values
k_ra8_okHandle filled.
k_ra8_err_null_ptrout was NULL or label/ikm missing where required.
k_ra8_err_invalid_argout_len zero or larger than the hash's max XOF length.
k_ra8_err_hw_timeoutEngine never signalled KDF_DONE.
Precondition
op is one of k_ra8_rsip_kdf_op_*.
out is non-NULL.
Postcondition
On success out carries a wrapped HMAC-SHA-256 handle.
Note
Thread safety: not thread-safe.
Since
0.1.0

Definition at line 727 of file ra8_rsip_asym.c.

References k_ra8_err_not_supported, RA8_CHECK_NULL_PTR, and s_tag.

◆ ra8_rsip_key_unwrap()

ra8_err_t ra8_rsip_key_unwrap ( const ra8_rsip_key_handle_t * kek,
const uint8_t * iv,
const uint8_t * blob,
ra8_rsip_key_handle_t * dest )
nodiscard

Unwrap a transportable blob into a key handle.

Parameters
[in]kekKey-encryption-key handle.
[in]iv16-byte wrap IV used at wrap time.
[in]blobWrapped blob (64 bytes).
[out]destDestination key handle.
Returns
ra8_err_t error code.
Return values
k_ra8_okHandle filled.
k_ra8_err_null_ptrAny pointer was NULL.
k_ra8_err_hw_timeoutEngine never signalled DONE.
k_ra8_err_hw_errorBlob authenticity check failed.
Precondition
kek->alg is an AES install opcode.
iv, blob, dest are non-NULL.
Postcondition
On success, dest carries the unwrapped algorithm + body.
Note
Thread safety: not thread-safe.
Since
0.1.0

Definition at line 715 of file ra8_rsip_asym.c.

References k_ra8_err_not_supported, RA8_CHECK_NULL_PTR, and s_tag.

◆ ra8_rsip_key_wrap()

ra8_err_t ra8_rsip_key_wrap ( const ra8_rsip_key_handle_t * kek,
const uint8_t * iv,
const ra8_rsip_key_handle_t * src,
uint8_t * blob )
nodiscard

Wrap a key handle into a transportable blob using a KEK.

Parameters
[in]kekKey-encryption-key handle.
[in]iv16-byte wrap IV.
[in]srcSource key handle to wrap.
[out]blobWrapped blob output (64 bytes).
Returns
ra8_err_t error code.
Return values
k_ra8_okBlob produced.
k_ra8_err_null_ptrAny pointer was NULL.
k_ra8_err_hw_timeoutEngine never signalled DONE.
Precondition
kek->alg is an AES install opcode.
iv is non-NULL.
Postcondition
On success, blob[0..63] is the wrapped blob.
Note
Thread safety: not thread-safe.
Since
0.1.0

Definition at line 703 of file ra8_rsip_asym.c.

References k_ra8_err_not_supported, RA8_CHECK_NULL_PTR, and s_tag.

◆ ra8_rsip_kv_count()

ra8_err_t ra8_rsip_kv_count ( uint32_t * out)
nodiscard

Snapshot the populated-slot count.

Parameters
[out]outReceives the count (0..16); never NULL.
Returns
ra8_err_t error code.
Return values
k_ra8_okCount returned.
k_ra8_err_null_ptrout was NULL.
Precondition
out is non-NULL.
ra8_rsip_init has been called.
Postcondition
*out is in [0..k_ra8_rsip_kv_slot_count].
No engine state is modified.
Note
Thread safety: read-only, safe to call concurrently.
Since
0.1.0

Definition at line 697 of file ra8_rsip_asym.c.

References k_ra8_err_not_supported, RA8_CHECK_NULL_PTR, and s_tag.

◆ ra8_rsip_kv_erase()

ra8_err_t ra8_rsip_kv_erase ( uint8_t slot)
nodiscard

Zeroise a vault slot.

Parameters
[in]slotSlot index.
Returns
ra8_err_t error code.
Return values
k_ra8_okSlot erased.
k_ra8_err_invalid_argslot out of range.
k_ra8_err_hw_timeoutEngine never signalled DONE.
Precondition
slot < k_ra8_rsip_kv_slot_count.
ra8_rsip_init has been called.
Postcondition
Slot reads back as zero.
Populated-slot count decremented if the slot was non-empty.
Note
Thread safety: not thread-safe.
Since
0.1.0

Definition at line 691 of file ra8_rsip_asym.c.

References k_ra8_err_not_supported.

◆ ra8_rsip_kv_read()

ra8_err_t ra8_rsip_kv_read ( uint8_t slot,
uint8_t * out )
nodiscard

Read a wrapped-key blob from a vault slot.

Parameters
[in]slotSlot index (0..k_ra8_rsip_kv_slot_count-1).
[out]out64-byte buffer to receive the wrapped blob.
Returns
ra8_err_t error code.
Return values
k_ra8_okBlob returned.
k_ra8_err_invalid_argslot out of range.
k_ra8_err_null_ptrout was NULL.
k_ra8_err_not_foundSlot is empty.
k_ra8_err_hw_timeoutEngine never signalled DONE.
Precondition
slot < k_ra8_rsip_kv_slot_count.
out is non-NULL.
Postcondition
On success, out[0..63] holds the slot blob.
Note
Thread safety: not thread-safe.
Since
0.1.0

Definition at line 677 of file ra8_rsip_asym.c.

References k_ra8_err_not_supported, RA8_CHECK_NULL_PTR, and s_tag.

◆ ra8_rsip_kv_write()

ra8_err_t ra8_rsip_kv_write ( uint8_t slot,
const uint8_t * in )
nodiscard

Write a wrapped-key blob into a vault slot.

Parameters
[in]slotSlot index.
[in]in64-byte wrapped blob.
Returns
ra8_err_t error code.
Return values
k_ra8_okSlot written.
k_ra8_err_invalid_argslot out of range.
k_ra8_err_null_ptrin was NULL.
k_ra8_err_hw_timeoutEngine never signalled DONE.
Precondition
slot < k_ra8_rsip_kv_slot_count.
in is non-NULL.
Postcondition
Slot now reads back as in.
Populated-slot count incremented if the slot was empty.
Note
Thread safety: not thread-safe.
Since
0.1.0

Definition at line 684 of file ra8_rsip_asym.c.

References k_ra8_err_not_supported, RA8_CHECK_NULL_PTR, and s_tag.

◆ ra8_rsip_oem_bl_version_get()

ra8_err_t ra8_rsip_oem_bl_version_get ( uint32_t * out)
nodiscard

Read the latched OEM boot loader version counter.

Parameters
[out]outReceives the 32-bit counter; never NULL.
Returns
ra8_err_t error code.
Return values
k_ra8_okSnapshot returned.
k_ra8_err_null_ptrout was NULL.
Precondition
out is non-NULL.
ra8_rsip_init has been called.
Postcondition
*out reflects the OEM_BL_VER cell.
No engine state is modified.
Note
Thread safety: read-only, safe to call concurrently.
Since
0.1.0

Definition at line 661 of file ra8_rsip_asym.c.

References k_ra8_err_not_supported, RA8_CHECK_NULL_PTR, and s_tag.

◆ ra8_rsip_oem_bl_version_increment()

ra8_err_t ra8_rsip_oem_bl_version_increment ( void )
nodiscard

Increment the OEM boot loader version (anti-rollback step).

Writes the inc-trigger word; the engine increments the counter monotonically. The lock register MUST be set after a successful boot to prevent further increments mid-flight.

Returns
ra8_err_t error code.
Return values
k_ra8_okCounter advanced.
k_ra8_err_invalid_stateOEM_BL_LOCK already latched.
Precondition
ra8_rsip_init has been called.
OEM_BL_LOCK is clear.
Postcondition
Counter has incremented by 1.
Counter value is observable via ra8_rsip_oem_bl_version_get.
Note
Thread safety: not thread-safe.
Since
0.1.0

Definition at line 667 of file ra8_rsip_asym.c.

References k_ra8_err_not_supported.

◆ ra8_rsip_oem_bl_version_lock()

ra8_err_t ra8_rsip_oem_bl_version_lock ( void )
nodiscard

Latch the OEM_BL_LOCK so further increments are rejected.

Returns
ra8_err_t error code.
Return values
k_ra8_okLock latched.
Precondition
ra8_rsip_init has been called.
Caller has finished any anti-rollback steps for this boot.
Postcondition
OEM_BL_LOCK reads as 1.
Subsequent ra8_rsip_oem_bl_version_increment returns k_ra8_err_invalid_state.
Note
Thread safety: not thread-safe.
Since
0.1.0

Definition at line 672 of file ra8_rsip_asym.c.

References k_ra8_err_not_supported.

Variable Documentation

◆ s_tag

const char* s_tag = "RSIP"
static

Logger tag used by every ra8_log_* call in this TU.

Kept short ("RSIP") so it fits in the fixed-width log prefix without truncation. Each RSIP translation unit keeps its own private copy.

Note
Static, file-scope.
Since
0.1.0

Definition at line 72 of file ra8_rsip_asym.c.