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

Secure-side sealed-key import implementation. More...

#include <stdint.h>
#include "key_import_internal.h"
#include "key_vault.h"
#include "ra8_attributes.h"
#include "ra8_check.h"
#include "ra8_err.h"
#include "ra8_secure.h"
#include "sec_cmac_internal.h"
Include dependency graph for key_import.c:

Go to the source code of this file.

Enumerations

enum  rotate_mask_t : uint8_t { k_rotate_mask_5bit = 31U }
 5-bit rotate-amount mask (mod 32). More...
enum  ra8_key_import_internal_t : uint8_t {
  k_handle_rotate_bits = 13U ,
  k_salt_reroll_rot = 7U
}
 Handle-obfuscation shift constants. More...
enum  ra8_key_import_mask_t : uint32_t {
  k_initial_salt = 0xA5A5A5A5U ,
  k_handle_high_bit_mask = 0x80000000U ,
  k_salt_reroll_xor = 0xDEADBEEFU
}
 32-bit handle/salt mixing masks and seeds. More...

Functions

static uint32_t internal_rotate_left_32 (uint32_t value, uint8_t amount)
 Rotate a 32-bit value left by amount bits (mod 32).
static uint32_t internal_handle_for_slot (uint16_t slot)
 Compute the opaque NS-side handle for a vault slot index.
static ra8_err_t internal_verify_cmac (const uint8_t *blob)
 Verify the trailing AES-CMAC of a sealed key blob.
ra8_err_t priv_ra8_key_import_reset (void)
 Reset the import allocator and reroll the per-boot salt.
ra8_err_t priv_ra8_key_import_seal (const uint8_t *blob, uint32_t blob_len, uint32_t *out_handle)
 Verify, store, and assign an opaque handle for a sealed key blob.
ra8_err_t priv_ra8_key_import_resolve (uint32_t handle, uint16_t *out_slot)
 Resolve a previously issued handle back to its vault slot.
ra8_err_t priv_ra8_key_import_build_blob (const uint8_t *material, uint8_t *out_blob)
 Build a sealed key blob from a raw 32-byte key (provisioning + test).

Variables

static const char * s_tag = "KEYIMP"
static uint16_t s_slot_used = 0U
 One bit per vault slot: 1 if currently allocated.
static uint32_t s_salt = (uint32_t)k_initial_salt
 Per-boot 32-bit salt used for handle obfuscation.

Detailed Description

Secure-side sealed-key import implementation.

Tag
[Ring 5 / SECAPP] {World: S}

Sits between the NSC veneer ra8_nsc_key_import and the underlying ra8_key_vault_store. The job here is twofold:

  • Authenticate the sealed blob with a real AES-CMAC (NIST SP 800-38B) over the 32 key bytes, keyed by the vault's key-authentication key (KAK). The CMAC is computed through the ra8_sec_cmac_* seam, so the firmware image runs the silicon-proven TF-PSA-Crypto psa_mac_* backend while host tests exercise a KAT-pinned in-tree reference. This replaces the forgeable length-tagged XOR fold that used to stand in for it; NS callers still see a binary go/no-go.
  • Hand back an opaque handle rather than the raw slot index. The handle is computed as slot ^ (s_salt rotated), so two different boots vend different handles for the same slot, and the slot index never leaks to NS.

The KAK is provisioned once, secure-side, via ra8_key_vault_set_mac_key and read back only through ra8_key_vault_load_mac_key – it lives in vault storage that is separate from the NS-importable slot array, so nothing the Non-Secure world can reach ever keys the MAC.

Definition in file key_import.c.

Enumeration Type Documentation

◆ ra8_key_import_internal_t

enum ra8_key_import_internal_t : uint8_t

Handle-obfuscation shift constants.

Rotating the 32-bit salt before XORing into the 16-bit slot decorrelates the low 16 bits of the salt from the high 16, so a caller who can observe many handles cannot recover the salt by differencing them.

Enumerator
k_handle_rotate_bits 

Salt rotate amount before slot XOR.

k_salt_reroll_rot 

Salt reroll rotate amount.

Definition at line 63 of file key_import.c.

◆ ra8_key_import_mask_t

enum ra8_key_import_mask_t : uint32_t

32-bit handle/salt mixing masks and seeds.

Enumerator
k_initial_salt 

Boot salt seed.

k_handle_high_bit_mask 

Forces a non-zero handle.

k_salt_reroll_xor 

Salt reroll mixing const.

Definition at line 69 of file key_import.c.

◆ rotate_mask_t

enum rotate_mask_t : uint8_t

5-bit rotate-amount mask (mod 32).

Enumerator
k_rotate_mask_5bit 

Rotate mask 5bit.

Definition at line 49 of file key_import.c.

Function Documentation

◆ internal_handle_for_slot()

uint32_t internal_handle_for_slot ( uint16_t slot)
static

Compute the opaque NS-side handle for a vault slot index.

Mixes the per-boot salt with the slot index so two boots vend different handles for the same slot, then forces bit 31 high so the value never collides with the reserved zero sentinel.

Parameters
[in]slotSlot index (0..k_ra8_key_vault_slots-1).
Returns
Opaque handle suitable for return to NS callers.
Return values
Alwaysa value with bit 31 set, never 0.
Precondition
slot was validated by the caller.
s_salt has been initialized by priv_ra8_key_import_reset or boot default.
Postcondition
No state is mutated.
Return value is deterministic for fixed (slot, s_salt).
Note
Pure helper; safe from any context.
Since
0.1.0

Definition at line 152 of file key_import.c.

References internal_rotate_left_32(), k_handle_high_bit_mask, k_handle_rotate_bits, RA8_INTERNAL, and s_salt.

Referenced by priv_ra8_key_import_resolve(), and priv_ra8_key_import_seal().

◆ internal_rotate_left_32()

uint32_t internal_rotate_left_32 ( uint32_t value,
uint8_t amount )
static

Rotate a 32-bit value left by amount bits (mod 32).

Used by both the salt rerolling step and the handle mixing so the bit distribution is well spread for sparse inputs.

Parameters
[in]valueSource 32-bit word.
[in]amountBit count; only the low 5 bits are used.
Returns
value rotated left by amount mod 32 bits.
Return values
``value``when amount mod 32 == 0.
Precondition
amount may take any uint8_t value.
Caller treats this as a pure expression (no side effects).
Postcondition
No state is mutated.
Return value depends only on the parameters.
Note
Pure helper; safe from any context.
Since
0.1.0

Definition at line 122 of file key_import.c.

References k_rotate_mask_5bit, and RA8_INTERNAL.

Referenced by internal_handle_for_slot(), and priv_ra8_key_import_reset().

◆ internal_verify_cmac()

ra8_err_t internal_verify_cmac ( const uint8_t * blob)
static

Verify the trailing AES-CMAC of a sealed key blob.

Loads the KAK from the vault, recomputes the AES-CMAC over the 32 key bytes via priv_ra8_sec_cmac_verify, and reports whether it matches the trailing k_ra8_key_import_mac_bytes of the blob. The KAK copy is wiped before return so no key material lingers on the secure stack.

Parameters
[in]blobSealed key blob; k_ra8_key_import_blob_bytes long.
Returns
ra8_err_t error code.
Return values
k_ra8_okCMAC authentic under the vault KAK.
k_ra8_err_invalid_argCMAC mismatch (blob tampered / wrong KAK).
k_ra8_err_not_foundNo KAK provisioned in the vault.
Precondition
blob is non-NULL and spans k_ra8_key_import_blob_bytes.
A KAK was provisioned via ra8_key_vault_set_mac_key.
Postcondition
No state is mutated; the KAK copy is wiped.
Return value is the authentication verdict only.
Note
Not thread-safe; secure-side serial dispatch only.
Since
0.1.0

Definition at line 185 of file key_import.c.

References k_ra8_key_import_key_bytes, k_ra8_key_import_mac_bytes, k_ra8_key_vault_mac_key_bytes, k_ra8_ok, priv_ra8_sec_cmac_verify(), RA8_INTERNAL, ra8_key_vault_load_mac_key(), and ra8_secure_memzero().

Referenced by priv_ra8_key_import_seal().

◆ priv_ra8_key_import_build_blob()

ra8_err_t priv_ra8_key_import_build_blob ( const uint8_t * material,
uint8_t * out_blob )
nodiscard

Build a sealed key blob from a raw 32-byte key (provisioning + test).

Build a sealed blob from a raw key (provisioning + test helper).

Copies the key bytes verbatim, computes the AES-CMAC over them with the vault KAK via priv_ra8_sec_cmac_compute, and writes the trailing k_ra8_key_import_mac_bytes of the blob. Provided so provisioning and unit tests can package a key the import path will accept.

Parameters
[in]materialRaw 32-byte key material.
[out]out_blobReceives k_ra8_key_import_blob_bytes of output.
Returns
ra8_err_t error code.
Return values
k_ra8_okBlob written.
k_ra8_err_null_ptrmaterial or out_blob was NULL.
k_ra8_err_not_foundNo KAK provisioned in the vault.
Precondition
material and out_blob are non-NULL.
A KAK was provisioned via ra8_key_vault_set_mac_key.
Postcondition
On success out_blob is accepted by internal_verify_cmac under the current KAK.
No global state is mutated.
Note
Not thread-safe.
See also
priv_ra8_key_import_seal
Since
0.1.0

Definition at line 369 of file key_import.c.

References k_ra8_key_import_key_bytes, k_ra8_key_vault_mac_key_bytes, k_ra8_ok, priv_ra8_sec_cmac_compute(), RA8_CHECK_NULL_PTR, ra8_key_vault_load_mac_key(), ra8_secure_memzero(), and s_tag.

◆ priv_ra8_key_import_reset()

ra8_err_t priv_ra8_key_import_reset ( void )
nodiscard

Reset the import allocator and reroll the per-boot salt.

Reset the import table (drops every handle) and re-seed the salt.

Clears every s_slot_used bit and rotates the salt with a fixed mixing constant so successive resets vend different handles for the same slot index. Falls back to the boot seed if the rerolled salt happens to be zero.

Returns
ra8_err_t error code.
Return values
k_ra8_okAlways; the operation cannot fail.
Precondition
Caller is in the secure-side init context.
No NS-side handle issued before the call may be considered live afterwards.
Postcondition
All slots are marked free.
s_salt is non-zero.
Note
Not thread-safe; reset belongs to the boot/test path.
Since
0.1.0

Definition at line 224 of file key_import.c.

References internal_rotate_left_32(), k_initial_salt, k_ra8_ok, k_salt_reroll_rot, k_salt_reroll_xor, s_salt, and s_slot_used.

◆ priv_ra8_key_import_resolve()

ra8_err_t priv_ra8_key_import_resolve ( uint32_t handle,
uint16_t * out_slot )
nodiscard

Resolve a previously issued handle back to its vault slot.

Resolve a handle to the underlying slot index.

Walks the live slot bitmap and recomputes the per-slot handle until a match is found. The slot index never leaves the secure world via the handle itself; this function is the only place that performs the inverse mapping.

Parameters
[in]handleOpaque handle previously returned by priv_ra8_key_import_seal.
[out]out_slotReceives the resolved slot index on success.
Returns
ra8_err_t error code.
Return values
k_ra8_okHandle matched a live slot.
k_ra8_err_null_ptrout_slot was NULL.
k_ra8_err_not_foundHandle does not match any live slot.
Precondition
out_slot is non-NULL.
Caller has previously issued the handle through priv_ra8_key_import_seal.
Postcondition
On success, *out_slot is in [0, k_ra8_key_vault_slots).
No vault state is mutated.
Note
Not thread-safe.
See also
priv_ra8_key_import_seal
Since
0.1.0

Definition at line 329 of file key_import.c.

References internal_handle_for_slot(), k_ra8_err_not_found, k_ra8_key_vault_slots, k_ra8_ok, RA8_CHECK_NULL_PTR, s_slot_used, and s_tag.

◆ priv_ra8_key_import_seal()

ra8_err_t priv_ra8_key_import_seal ( const uint8_t * blob,
uint32_t blob_len,
uint32_t * out_handle )
nodiscard

Verify, store, and assign an opaque handle for a sealed key blob.

Validate a sealed blob and import the key into a free slot.

Validates the blob length, checks the AES-CMAC, allocates the lowest free vault slot, copies the key into the vault, and returns an opaque handle that the NS world can later present to the SHA-256 challenge primitive without ever learning the slot index.

Parameters
[in]blobSealed key blob.
[in]blob_lenLength of blob; must equal k_ra8_key_import_blob_bytes.
[out]out_handleReceives the opaque handle on success.
Returns
ra8_err_t error code.
Return values
k_ra8_okKey sealed and handle issued.
k_ra8_err_null_ptrblob or out_handle was NULL.
k_ra8_err_invalid_sizeblob_len did not match expected size.
k_ra8_err_invalid_argCMAC verification failed.
k_ra8_err_not_foundNo KAK provisioned in the vault.
k_ra8_err_no_memAll vault slots are in use.
Precondition
blob and out_handle are non-NULL.
A KAK was provisioned via ra8_key_vault_set_mac_key.
Postcondition
On success, the chosen slot bit is set in s_slot_used.
On error, no vault slot is mutated.
Note
Not thread-safe; secure-side serial dispatch only.
See also
priv_ra8_key_import_resolve
Since
0.1.0

Definition at line 268 of file key_import.c.

References internal_handle_for_slot(), internal_verify_cmac(), k_ra8_err_invalid_size, k_ra8_err_no_mem, k_ra8_key_import_blob_bytes, k_ra8_key_vault_slots, k_ra8_ok, RA8_CHECK_NULL_PTR, ra8_key_vault_store(), s_slot_used, and s_tag.

Variable Documentation

◆ s_salt

uint32_t s_salt = (uint32_t)k_initial_salt
static

Per-boot 32-bit salt used for handle obfuscation.

Refreshed on every priv_ra8_key_import_reset call. The chosen value is intentionally non-zero so the handle for slot 0 never collides with k_ra8_key_import_handle_zero.

Warning
Do not write directly; call priv_ra8_key_import_reset.
Since
0.1.0

Definition at line 99 of file key_import.c.

Referenced by internal_handle_for_slot(), and priv_ra8_key_import_reset().

◆ s_slot_used

uint16_t s_slot_used = 0U
static

One bit per vault slot: 1 if currently allocated.

Bit i of s_slot_used is set when slot i has been imported via priv_ra8_key_import_seal. priv_ra8_key_import_reset clears the entire mask.

Note
Direct modification from anywhere outside this TU is forbidden.
Since
0.1.0

Definition at line 86 of file key_import.c.

Referenced by priv_ra8_key_import_reset(), priv_ra8_key_import_resolve(), and priv_ra8_key_import_seal().

◆ s_tag

const char* s_tag = "KEYIMP"
static

Definition at line 46 of file key_import.c.