ra8-firmware 0.1.0
Bare-metal firmware for the Renesas RA8 family (RA8D2 / RA8P1)
Loading...
Searching...
No Matches
key_import.c
Go to the documentation of this file.
1
35
36#include <stdint.h>
37
38#include "key_import_internal.h"
39#include "key_vault.h"
40#include "ra8_attributes.h"
41#include "ra8_check.h"
42#include "ra8_err.h"
43#include "ra8_secure.h"
44#include "sec_cmac_internal.h"
45
46static const char* s_tag = "KEYIMP";
47
49typedef enum : uint8_t {
52
67
69typedef enum : uint32_t {
70 k_initial_salt = 0xA5A5A5A5U,
71 k_handle_high_bit_mask = 0x80000000U,
72 k_salt_reroll_xor = 0xDEADBEEFU,
74
86static uint16_t s_slot_used = 0U;
87
99static uint32_t s_salt = (uint32_t)k_initial_salt;
100
122RA8_INTERNAL static uint32_t internal_rotate_left_32(uint32_t value, uint8_t amount)
123{
124 const uint8_t bits = (uint8_t)(amount & (uint8_t)k_rotate_mask_5bit);
125 if (bits == 0U) {
126 return value;
127 }
128 return (value << bits) | (value >> (32U - bits));
129}
130
152RA8_INTERNAL static uint32_t internal_handle_for_slot(uint16_t slot)
153{
154 const uint32_t mixed = internal_rotate_left_32(s_salt, k_handle_rotate_bits);
155 /* Force a non-zero handle: OR in bit 31 so we never collide with
156 * the reserved zero sentinel even if the XOR happens to produce 0. */
157 return ((uint32_t)slot ^ mixed) | (uint32_t)k_handle_high_bit_mask;
158}
159
185RA8_INTERNAL static ra8_err_t internal_verify_cmac(const uint8_t* blob)
186{
187 uint8_t mac_key[k_ra8_key_vault_mac_key_bytes];
188 uint16_t mac_key_len = 0U;
189 const ra8_err_t kerr =
190 ra8_key_vault_load_mac_key(mac_key, (uint16_t)sizeof(mac_key), &mac_key_len);
191 if (kerr != k_ra8_ok) {
192 return kerr;
193 }
194 const ra8_err_t verr = priv_ra8_sec_cmac_verify(mac_key,
195 mac_key_len,
196 blob,
200 ra8_secure_memzero(mac_key, sizeof(mac_key));
201 return verr;
202}
203
225{
226 s_slot_used = 0U;
227 /* Bump the salt with a fixed mixing constant so successive resets
228 * also produce different handles. */
229 s_salt =
231 if (s_salt == 0U) {
232 s_salt = (uint32_t)k_initial_salt;
233 }
234 return k_ra8_ok;
235}
236
268ra8_err_t priv_ra8_key_import_seal(const uint8_t* blob, uint32_t blob_len, uint32_t* out_handle)
269{
270 RA8_CHECK_NULL_PTR(blob, s_tag, "seal: blob");
271 RA8_CHECK_NULL_PTR(out_handle, s_tag, "seal: out_handle");
272 if (blob_len != (uint32_t)k_ra8_key_import_blob_bytes) {
274 }
275 const ra8_err_t mac_err = internal_verify_cmac(blob);
276 if (mac_err != k_ra8_ok) {
277 return mac_err;
278 }
279
280 /* Pick the lowest free slot. Loop bound is the slot count -- NASA
281 * Rule 2 compliant. */
282 uint16_t chosen = (uint16_t)k_ra8_key_vault_slots;
283 for (uint16_t i = 0U; i < (uint16_t)k_ra8_key_vault_slots; ++i) {
284 const uint16_t bit = (uint16_t)((uint16_t)1U << i);
285 if ((s_slot_used & bit) == 0U) {
286 chosen = i;
287 break;
288 }
289 }
290 if (chosen == (uint16_t)k_ra8_key_vault_slots) {
291 return k_ra8_err_no_mem;
292 }
293
294 const ra8_err_t store_err = ra8_key_vault_store(chosen, blob);
295 if (store_err != k_ra8_ok) {
296 return store_err;
297 }
298 s_slot_used = (uint16_t)(s_slot_used | (uint16_t)((uint16_t)1U << chosen));
299 *out_handle = internal_handle_for_slot(chosen);
300 return k_ra8_ok;
301}
302
329ra8_err_t priv_ra8_key_import_resolve(uint32_t handle, uint16_t* out_slot)
330{
331 RA8_CHECK_NULL_PTR(out_slot, s_tag, "resolve: out_slot");
332 for (uint16_t i = 0U; i < (uint16_t)k_ra8_key_vault_slots; ++i) {
333 const uint16_t bit = (uint16_t)((uint16_t)1U << i);
334 if (((s_slot_used & bit) != 0U) && (internal_handle_for_slot(i) == handle)) {
335 *out_slot = i;
336 return k_ra8_ok;
337 }
338 }
339 return k_ra8_err_not_found;
340}
341
369ra8_err_t priv_ra8_key_import_build_blob(const uint8_t* material, uint8_t* out_blob)
370{
371 RA8_CHECK_NULL_PTR(material, s_tag, "build_blob: material");
372 RA8_CHECK_NULL_PTR(out_blob, s_tag, "build_blob: out_blob");
373 uint8_t mac_key[k_ra8_key_vault_mac_key_bytes];
374 uint16_t mac_key_len = 0U;
375 const ra8_err_t kerr =
376 ra8_key_vault_load_mac_key(mac_key, (uint16_t)sizeof(mac_key), &mac_key_len);
377 if (kerr != k_ra8_ok) {
378 return kerr;
379 }
380 for (uint16_t i = 0U; i < (uint16_t)k_ra8_key_import_key_bytes; ++i) {
381 out_blob[i] = material[i];
382 }
383 const ra8_err_t cerr = priv_ra8_sec_cmac_compute(mac_key,
384 mac_key_len,
385 material,
387 &out_blob[k_ra8_key_import_key_bytes]);
388 ra8_secure_memzero(mac_key, sizeof(mac_key));
389 return cerr;
390}
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.
Definition key_import.c:268
static uint32_t internal_rotate_left_32(uint32_t value, uint8_t amount)
Rotate a 32-bit value left by amount bits (mod 32).
Definition key_import.c:122
static uint32_t s_salt
Per-boot 32-bit salt used for handle obfuscation.
Definition key_import.c:99
ra8_key_import_internal_t
Handle-obfuscation shift constants.
Definition key_import.c:63
@ k_salt_reroll_rot
Salt reroll rotate amount.
Definition key_import.c:65
@ k_handle_rotate_bits
Salt rotate amount before slot XOR.
Definition key_import.c:64
static ra8_err_t internal_verify_cmac(const uint8_t *blob)
Verify the trailing AES-CMAC of a sealed key blob.
Definition key_import.c:185
ra8_key_import_mask_t
32-bit handle/salt mixing masks and seeds.
Definition key_import.c:69
@ k_salt_reroll_xor
Salt reroll mixing const.
Definition key_import.c:72
@ k_handle_high_bit_mask
Forces a non-zero handle.
Definition key_import.c:71
@ k_initial_salt
Boot salt seed.
Definition key_import.c:70
static uint16_t s_slot_used
One bit per vault slot: 1 if currently allocated.
Definition key_import.c:86
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).
Definition key_import.c:369
rotate_mask_t
5-bit rotate-amount mask (mod 32).
Definition key_import.c:49
@ k_rotate_mask_5bit
Rotate mask 5bit.
Definition key_import.c:50
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.
Definition key_import.c:329
static uint32_t internal_handle_for_slot(uint16_t slot)
Compute the opaque NS-side handle for a vault slot index.
Definition key_import.c:152
ra8_err_t priv_ra8_key_import_reset(void)
Reset the import allocator and reroll the per-boot salt.
Definition key_import.c:224
Secure-side sealed key import + opaque handle vending.
@ k_ra8_key_import_key_bytes
Key portion length.
@ k_ra8_key_import_mac_bytes
Trailing AES-CMAC tag length.
@ k_ra8_key_import_blob_bytes
32-byte key + 16-byte CMAC.
Secure-only symmetric key store.
ra8_err_t ra8_key_vault_store(uint16_t slot, const uint8_t *key)
Programme a 256-bit symmetric key into a vault slot.
Definition key_vault.c:567
@ k_ra8_key_vault_mac_key_bytes
Max key-authentication key.
Definition key_vault.h:61
@ k_ra8_key_vault_slots
Number of stored keys.
Definition key_vault.h:57
ra8_err_t ra8_key_vault_load_mac_key(uint8_t *out, uint16_t out_cap, uint16_t *out_len)
Copy the provisioned key-authentication key for a secure caller.
Definition key_vault.c:589
static const char * s_tag
Logging / check tag.
Definition ra8_app.c:17
Annotation-attribute framework macros for ra8-firmware.
#define RA8_INTERNAL
Marker that a function is intended to be static (file-local).
Validation and Error-Checking Macros for ra8-firmware.
#define RA8_CHECK_NULL_PTR(ptr, tag, message)
Reject nullptr pointer, returning k_ra8_err_null_ptr.
Definition ra8_check.h:243
Error Code Definitions for ra8-firmware.
@ k_ra8_err_no_mem
Static buffer exhausted (no dynamic memory on this project).
Definition ra8_err.h:142
@ k_ra8_ok
Success – operation completed with all postconditions satisfied.
Definition ra8_err.h:119
@ k_ra8_err_not_found
Requested item not found (lookup / search missed).
Definition ra8_err.h:173
@ k_ra8_err_invalid_size
Invalid size parameter (too large, too small, or misaligned).
Definition ra8_err.h:167
ra8_err_codes_t ra8_err_t
Canonical error-return type used by every ra8-firmware API.
Definition ra8_err.h:546
Secure-comparison primitives for the crypto / secure-boot paths.
void ra8_secure_memzero(void *ptr, size_t len)
Securely zero a buffer such that the write cannot be optimised away.
Definition ra8_secure.c:37
ra8_err_t priv_ra8_sec_cmac_compute(const uint8_t *key, uint16_t key_len, const uint8_t *msg, uint32_t msg_len, uint8_t *out_mac)
Compute the AES-CMAC tag of a message under a symmetric key.
Definition sec_cmac.c:632
ra8_err_t priv_ra8_sec_cmac_verify(const uint8_t *key, uint16_t key_len, const uint8_t *msg, uint32_t msg_len, const uint8_t *mac, uint16_t mac_len)
Verify an AES-CMAC tag against a message under a symmetric key.
Definition sec_cmac.c:647
Secure-side AES-CMAC seam (real PSA backend / in-tree reference).