ra8-firmware 0.1.0
Bare-metal firmware for the Renesas RA8 family (RA8D2 / RA8P1)
Loading...
Searching...
No Matches
ra8_rsip_asym.c
Go to the documentation of this file.
1
49
50#include <stdint.h>
51
52#include "ra8_attributes.h"
53#include "ra8_check.h"
54#include "ra8_err.h"
55#include "ra8_log.h"
56#include "ra8_rsip.h"
58#include "ra8_rsip_internal.h"
59#include "ra8_rsip_regs.h"
60
72static const char* s_tag = "RSIP";
73
74/*
75 * The RSIP-E50D generic hash / HMAC family and the whole key-management surface
76 * (OEM anti-rollback counter, wrapped-key vault, KEK wrap / unwrap, HKDF / HUK /
77 * UID key derivation, DOTF key routing) are NOT backed by a documented register
78 * interface on this silicon. HUM Ch 52 "Renesas Secure IP (RSIP-E50D)" is a
79 * six-page feature overview (p 3302-3307) with no hash / key command-register
80 * map; the vendor engine is driven through an encrypted firmware mailbox, not
81 * the MMIO opcodes modelled below. The command-path bodies here only round-trip
82 * the host register fake; they do NOT compute a real digest, HMAC, wrapped
83 * key, or derived key. They compile only under the insecure-stub / fake
84 * guard so a production image gets the fail-closed #else and can never mistake
85 * these bytes for a valid hash, MAC, or key handle. The only real hash path is
86 * ra8_rsip_sha256 -> the software SHA-256 backend in ra8_rsip.c (untouched); any
87 * real hash / HMAC / KDF need is served by tf-psa-crypto on the M85,
88 * silicon-proven in psa_crypto_hil (issue #215). The register pokes below
89 * therefore carry NO HUM citation: there is no real register map to cite. The
90 * former "HUM Ch 52.1" / "52.2.3" citations were fabricated and are removed.
91 */
92#if defined(RA8_INSECURE_STUB_CRYPTO) || defined(RA8_OFF_TARGET)
93
94/* ===========================================================================
95 * Round-3 entry points: hash + HMAC (off-target-only fiction)
96 * ===========================================================================
97 */
98
99/* Map a hash algorithm selector to its natural digest length -- see surrounding code and HUM citations. */
101static uint32_t internal_hash_size(ra8_rsip_hash_alg_t alg)
102{
103 switch (alg) {
107 return (uint32_t)k_ra8_rsip_sha224_digest_bytes;
111 return (uint32_t)k_ra8_rsip_sha256_digest_bytes;
114 return (uint32_t)k_ra8_rsip_sha384_digest_bytes;
117 return (uint32_t)k_ra8_rsip_sha512_digest_bytes;
120 /* Variable-length output: caller supplies. */
121 return 1U;
122 default:
123 return 0U;
124 }
125}
126
127/* Validate the hash + digest length arguments before any MMIO -- see surrounding code and HUM citations. */
129static ra8_err_t internal_hash_validate(ra8_rsip_hash_alg_t alg,
130 const uint8_t* msg,
131 uint32_t msg_len,
132 uint32_t digest_len,
133 uint32_t* needed)
134{
135 if ((msg == nullptr) && (msg_len != 0U)) {
136 return k_ra8_err_null_ptr;
137 }
138 const uint32_t n = internal_hash_size(alg);
139 if (n == 0U) {
141 }
142 if ((alg != k_ra8_rsip_hash_shake128) && (alg != k_ra8_rsip_hash_shake256) && (digest_len < n)) {
144 }
145 *needed = n;
146 return k_ra8_ok;
147}
148
149/* Read a variable-length digest from the modelled HASH_DIGEST window -- see implementation for details. */
151static void internal_hash_pull_digest(uint8_t* digest, uint32_t to_read)
152{
153 uint32_t i = 0U;
154 uint32_t off = (uint32_t)k_ra8_rsip_off_hash_digest;
155 while ((i + (uint32_t)k_ra8_rsip_trng_word_bytes) <= to_read) {
156 /* Computed digest-word offset is a modelled register location (off-target-only
157 * fiction), not a literal enumerator -- the analyzer can't see that. */
158 const uint32_t word = *ra8_rsip_reg32((ra8_rsip_off_t)off);
159 priv_unpack_le(word, &digest[i]);
160 i += (uint32_t)k_ra8_rsip_trng_word_bytes;
161 off += (uint32_t)k_ra8_rsip_trng_word_bytes;
162 }
163 if (i < to_read) {
164 const uint32_t word = *ra8_rsip_reg32((ra8_rsip_off_t)off);
165 for (uint32_t b = 0U; (i + b) < to_read; ++b) {
166 digest[i + b] = (uint8_t)((word >> (b * k_ra8_rsip_byte_bits)) & k_ra8_rsip_byte_mask);
167 }
168 }
170}
171
173 const uint8_t* msg,
174 uint32_t msg_len,
175 uint8_t* digest,
176 uint32_t digest_len)
177{
178 RA8_CHECK_NULL_PTR(digest, s_tag, "digest must not be nullptr");
179 uint32_t needed = 0U;
180 const ra8_err_t v_err = internal_hash_validate(alg, msg, msg_len, digest_len, &needed);
181 RA8_RETURN_ON_ERROR(v_err, s_tag, "rsip_hash: validate");
182
184
185 if (msg_len > 0U) {
187 }
188
189 /* Wait for DONE; the bounded poll routes through the host wait seam. */
190 const ra8_err_t wait_err = priv_hash_wait_done();
191 RA8_RETURN_ON_ERROR(wait_err, s_tag, "rsip_hash: hash done");
192
193 /* Read digest_len for SHAKE; algo-natural otherwise. */
194 const uint32_t to_read =
195 ((alg == k_ra8_rsip_hash_shake128) || (alg == k_ra8_rsip_hash_shake256)) ? digest_len : needed;
196 internal_hash_pull_digest(digest, to_read);
197 return k_ra8_ok;
198}
199
201 const uint8_t* msg,
202 uint32_t msg_len,
203 uint8_t* mac,
204 uint32_t mac_len)
205{
206 RA8_CHECK_NULL_PTR(key, s_tag, "key must not be nullptr");
207 RA8_CHECK_NULL_PTR(mac, s_tag, "mac must not be nullptr");
208 if ((msg == nullptr) && (msg_len != 0U)) {
209 return k_ra8_err_null_ptr;
210 }
211 /* Determine the underlying hash size from the install opcode. */
212 uint32_t needed = 0U;
213 switch (key->alg) {
216 needed = (uint32_t)k_ra8_rsip_sha224_digest_bytes;
217 break;
220 needed = (uint32_t)k_ra8_rsip_sha256_digest_bytes;
221 break;
223 needed = (uint32_t)k_ra8_rsip_sha384_digest_bytes;
224 break;
226 needed = (uint32_t)k_ra8_rsip_sha512_digest_bytes;
227 break;
228 default:
230 }
231 if (mac_len < needed) {
233 }
234 /* Stage HMAC key handle, then drive the hash unit in HMAC mode. */
236 priv_load_handle(key);
237 return ra8_rsip_hash(k_ra8_rsip_hash_sha256, msg, msg_len, mac, needed);
238}
239
240/* ===========================================================================
241 * Round-3: asymmetric byte-lane + handle-tail helpers
242 *
243 * Shared with ra8_rsip_rsa.c / ra8_rsip_ecc.c via ra8_rsip_asym_internal.h. Every
244 * consumer references them only from inside its own stub-crypto guard, so they
245 * live inside the guard here and are absent from a production image.
246 * ===========================================================================
247 */
248
249/* Zero-fill the unused tail of a key-handle body buffer -- see ra8_rsip_asym_internal.h. */
250void internal_zero_handle_tail(ra8_rsip_key_handle_t* handle, uint32_t words)
251{
252 for (uint32_t w = words; w < (uint32_t)k_ra8_rsip_handle_words_rsa4096_priv; ++w) {
253 handle->body[w] = 0U;
254 }
255}
256
257/* Push a buffer through an asymmetric input lane (off-target-only fiction) -- see implementation for details. */
258void internal_asym_push(ra8_rsip_off_t off, const uint8_t* buf, uint32_t len)
259{
260 uint32_t i = 0U;
261 while ((i + (uint32_t)k_ra8_rsip_trng_word_bytes) <= len) {
262 *ra8_rsip_reg32(off) = priv_pack_le(&buf[i]);
263 i += (uint32_t)k_ra8_rsip_trng_word_bytes;
264 }
265 if (i < len) {
266 uint32_t tail = 0U;
267 for (uint32_t b = 0U; (i + b) < len; ++b) {
268 tail |= ((uint32_t)buf[i + b]) << (b * k_ra8_rsip_byte_bits);
269 }
270 *ra8_rsip_reg32(off) = tail;
271 }
272}
273
274/* Pull a buffer back through an asymmetric output lane (off-target-only fiction) -- see implementation for details. */
275void internal_asym_pull(ra8_rsip_off_t off, uint8_t* buf, uint32_t len)
276{
277 uint32_t i = 0U;
278 while ((i + (uint32_t)k_ra8_rsip_trng_word_bytes) <= len) {
279 priv_unpack_le(*ra8_rsip_reg32(off), &buf[i]);
280 i += (uint32_t)k_ra8_rsip_trng_word_bytes;
281 }
282 if (i < len) {
283 const uint32_t word = *ra8_rsip_reg32(off);
284 for (uint32_t b = 0U; (i + b) < len; ++b) {
285 buf[i + b] = (uint8_t)((word >> (b * k_ra8_rsip_byte_bits)) & k_ra8_rsip_byte_mask);
286 }
287 }
288}
289
290/* ===========================================================================
291 * Round-3 entry points: OEM boot loader version (anti-rollback, off-target-only fiction)
292 * ===========================================================================
293 */
294
296{
297 RA8_CHECK_NULL_PTR(out, s_tag, "out must not be nullptr");
299 return k_ra8_ok;
300}
301
303{
306 }
307 /* W1 trigger; engine increments the latched counter. */
310 return k_ra8_ok;
311}
312
314{
316 return k_ra8_ok;
317}
318
319/* ===========================================================================
320 * Round-3 entry points: wrapped-key vault (off-target-only fiction)
321 * ===========================================================================
322 */
323
324/* Issue a vault command and wait for completion -- see implementation for details. */
326static ra8_err_t internal_kv_op(ra8_rsip_kv_op_t op, uint8_t slot)
327{
329 *ra8_rsip_reg32(k_ra8_rsip_off_kv_ctrl) = (uint32_t)op;
330 *ra8_rsip_reg32(k_ra8_rsip_off_mbox_op) = (uint32_t)op;
332}
333
334ra8_err_t ra8_rsip_kv_read(uint8_t slot, uint8_t* out)
335{
336 RA8_CHECK_NULL_PTR(out, s_tag, "out must not be nullptr");
337 if (slot >= (uint8_t)k_ra8_rsip_kv_slot_count) {
339 }
340 const ra8_err_t err = internal_kv_op(k_ra8_rsip_kv_op_read, slot);
341 if (err != k_ra8_ok) {
342 return err;
343 }
344 for (uint32_t w = 0U; w < k_ra8_rsip_kv_slot_w; ++w) {
345 const uint32_t word = *ra8_rsip_reg32(k_ra8_rsip_off_kv_data);
346 priv_unpack_le(word, &out[(size_t)w * (size_t)k_ra8_rsip_trng_word_bytes]);
347 }
348 return k_ra8_ok;
349}
350
351ra8_err_t ra8_rsip_kv_write(uint8_t slot, const uint8_t* in)
352{
353 RA8_CHECK_NULL_PTR(in, s_tag, "in must not be nullptr");
354 if (slot >= (uint8_t)k_ra8_rsip_kv_slot_count) {
356 }
357 for (uint32_t w = 0U; w < k_ra8_rsip_kv_slot_w; ++w) {
359 priv_pack_le(&in[(size_t)w * (size_t)k_ra8_rsip_trng_word_bytes]);
360 }
361 return internal_kv_op(k_ra8_rsip_kv_op_write, slot);
362}
363
364ra8_err_t ra8_rsip_kv_erase(uint8_t slot)
365{
366 if (slot >= (uint8_t)k_ra8_rsip_kv_slot_count) {
368 }
369 return internal_kv_op(k_ra8_rsip_kv_op_erase, slot);
370}
371
372ra8_err_t ra8_rsip_kv_count(uint32_t* out)
373{
374 RA8_CHECK_NULL_PTR(out, s_tag, "out must not be nullptr");
376 return k_ra8_ok;
377}
378
379/* ===========================================================================
380 * Round-3 entry points: key wrap / unwrap engine (off-target-only fiction)
381 * ===========================================================================
382 */
383
406static void internal_kw_stage_kek(const ra8_rsip_key_handle_t* kek, const uint8_t* iv)
407{
411 iv,
412 (uint32_t)k_ra8_rsip_iv_words * (uint32_t)k_ra8_rsip_trng_word_bytes);
413}
414
415/* Stream the wrap-engine output blob (16 words) into a byte buffer -- see implementation for details. */
417static void internal_kw_pull_blob(uint8_t* blob)
418{
419 for (uint32_t w = 0U; w < k_ra8_rsip_kv_slot_w; ++w) {
420 const uint32_t word = *ra8_rsip_reg32(k_ra8_rsip_off_kw_blob_out);
421 priv_unpack_le(word, &blob[(size_t)w * (size_t)k_ra8_rsip_trng_word_bytes]);
422 }
423}
424
425/* Push the source-handle body into the wrap-engine input FIFO -- see implementation for details. */
427static void internal_kw_push_src(const ra8_rsip_key_handle_t* src)
428{
430 for (uint32_t w = 0U; w < src->body_words; ++w) {
432 }
433}
434
436 const uint8_t* iv,
437 const ra8_rsip_key_handle_t* src,
438 uint8_t* blob)
439{
440 RA8_CHECK_NULL_PTR(kek, s_tag, "kek must not be nullptr");
441 RA8_CHECK_NULL_PTR(iv, s_tag, "iv must not be nullptr");
442 RA8_CHECK_NULL_PTR(src, s_tag, "src must not be nullptr");
443 RA8_CHECK_NULL_PTR(blob, s_tag, "blob must not be nullptr");
444 if (priv_aes_alg_byte(kek->alg) == 0U) {
446 }
447 internal_kw_stage_kek(kek, iv);
448 internal_kw_push_src(src);
451
453 if (err != k_ra8_ok) {
454 return err;
455 }
456 internal_kw_pull_blob(blob);
457 return k_ra8_ok;
458}
459
460/* Pull the unwrapped algorithm + body into a destination handle -- see implementation for details. */
462static ra8_err_t internal_kw_pull_handle(ra8_rsip_key_handle_t* dest)
463{
464 /* Pull the unwrapped algorithm + body out. */
466 const uint32_t words = priv_handle_words_for((ra8_rsip_oem_cmd_t)dest->alg);
467 if (words == 0U) {
468 return k_ra8_err_hw_error;
469 }
470 dest->body_words = words;
471 for (uint32_t w = 0U; w < words; ++w) {
473 }
474 internal_zero_handle_tail(dest, words);
475 return k_ra8_ok;
476}
477
479 const uint8_t* iv,
480 const uint8_t* blob,
482{
483 RA8_CHECK_NULL_PTR(kek, s_tag, "kek must not be nullptr");
484 RA8_CHECK_NULL_PTR(iv, s_tag, "iv must not be nullptr");
485 RA8_CHECK_NULL_PTR(blob, s_tag, "blob must not be nullptr");
486 RA8_CHECK_NULL_PTR(dest, s_tag, "dest must not be nullptr");
487 if (priv_aes_alg_byte(kek->alg) == 0U) {
489 }
490 internal_kw_stage_kek(kek, iv);
491 for (uint32_t w = 0U; w < k_ra8_rsip_kv_slot_w; ++w) {
493 priv_pack_le(&blob[(size_t)w * (size_t)k_ra8_rsip_trng_word_bytes]);
494 }
497
499 if (err != k_ra8_ok) {
500 return err;
501 }
502 return internal_kw_pull_handle(dest);
503}
504
505/* ===========================================================================
506 * Round-3 entry points: key derivation (off-target-only fiction)
507 * ===========================================================================
508 */
509
510/* Validate the KDF arguments before any MMIO is touched -- see surrounding code and HUM citations. */
512static ra8_err_t internal_kdf_validate(ra8_rsip_kdf_op_t op,
513 const ra8_rsip_key_handle_t* ikm,
514 const uint8_t* label,
515 uint32_t label_len,
516 const uint8_t* salt,
517 uint32_t salt_len,
518 uint32_t out_len)
519{
520 if ((label == nullptr) && (label_len != 0U)) {
521 return k_ra8_err_null_ptr;
522 }
523 if ((salt == nullptr) && (salt_len != 0U)) {
524 return k_ra8_err_null_ptr;
525 }
526 if (out_len == 0U) {
528 }
529 /* HKDF modes need an IKM handle; HUK / UID modes do not. */
532 (ikm == nullptr)) {
533 return k_ra8_err_null_ptr;
534 }
535 return k_ra8_ok;
536}
537
538/* Stage the KDF inputs (op + length + optional IKM + label + salt) -- see implementation for details. */
540static void internal_kdf_stage(ra8_rsip_kdf_op_t op,
541 const ra8_rsip_key_handle_t* ikm,
542 const uint8_t* label,
543 uint32_t label_len,
544 const uint8_t* salt,
545 uint32_t salt_len,
546 uint32_t out_len)
547{
550 if (ikm != nullptr) {
553 }
554 if (label_len > 0U) {
556 }
557 if (salt_len > 0U) {
559 }
560}
561
562/* Pull the wrapped derived-key handle out of the KDF engine -- see implementation for details. */
564static void internal_kdf_pull_handle(ra8_rsip_key_handle_t* out)
565{
566 /* Wrapped derived key delivered through KDF_OUT. */
569 for (uint32_t w = 0U; w < out->body_words; ++w) {
571 }
573}
574
576 const ra8_rsip_key_handle_t* ikm,
577 const uint8_t* label,
578 uint32_t label_len,
579 const uint8_t* salt,
580 uint32_t salt_len,
581 uint32_t out_len,
583{
584 RA8_CHECK_NULL_PTR(out, s_tag, "out must not be nullptr");
585 const ra8_err_t v_err = internal_kdf_validate(op, ikm, label, label_len, salt, salt_len, out_len);
586 RA8_RETURN_ON_ERROR(v_err, s_tag, "rsip_kdf: validate");
587
588 internal_kdf_stage(op, ikm, label, label_len, salt, salt_len, out_len);
589 *ra8_rsip_reg32(k_ra8_rsip_off_mbox_op) = (uint32_t)op;
590
592 if (err != k_ra8_ok) {
593 return err;
594 }
595 internal_kdf_pull_handle(out);
596 return k_ra8_ok;
597}
598
599/* ===========================================================================
600 * Round-3 entry points: DOTF key delivery routing (off-target-only fiction)
601 * ===========================================================================
602 */
603
604ra8_err_t ra8_rsip_dotf_route(uint8_t which, uint8_t slot, bool on)
605{
606 if (which > 1U) {
608 }
609 if (on && (slot >= (uint8_t)k_ra8_rsip_kv_slot_count)) {
611 }
613 /* DOTFn_CTRL = (slot << 16) | route_enable */
614 uint32_t word = k_ra8_rsip_dotf_off;
615 if (on) {
616 word = ((uint32_t)slot << k_ra8_rsip_byte_shift_2) | k_ra8_rsip_dotf_on;
617 }
618 *ra8_rsip_reg32(off) = word;
619 return k_ra8_ok;
620}
621
622#else /* production build: neither RA8_INSECURE_STUB_CRYPTO nor RA8_OFF_TARGET */
623
624/*
625 * Fail-closed production variant. With no real RSIP hash / HMAC / key-management
626 * backend on this silicon, every entry point returns a hard error (never
627 * k_ra8_ok) so a production image cannot mistake the fake command-path for a
628 * real digest, MAC, wrapped key, or derived key. The only real hash is
629 * ra8_rsip_sha256 -> the software SHA-256 backend in ra8_rsip.c; callers needing
630 * hash / HMAC / KDF use tf-psa-crypto on the M85 (issue #215).
631 */
632
634 const uint8_t* msg,
635 uint32_t msg_len,
636 uint8_t* digest,
637 uint32_t digest_len)
638{
639 RA8_CHECK_NULL_PTR(digest, s_tag, "hash: digest must not be nullptr");
640 (void)alg;
641 (void)msg;
642 (void)msg_len;
643 (void)digest_len;
645}
646
648 const uint8_t* msg,
649 uint32_t msg_len,
650 uint8_t* mac,
651 uint32_t mac_len)
652{
653 RA8_CHECK_NULL_PTR(key, s_tag, "hmac: key must not be nullptr");
654 RA8_CHECK_NULL_PTR(mac, s_tag, "hmac: mac must not be nullptr");
655 (void)msg;
656 (void)msg_len;
657 (void)mac_len;
659}
660
662{
663 RA8_CHECK_NULL_PTR(out, s_tag, "oem_bl_version_get: out must not be nullptr");
665}
666
671
676
677ra8_err_t ra8_rsip_kv_read(uint8_t slot, uint8_t* out)
678{
679 RA8_CHECK_NULL_PTR(out, s_tag, "kv_read: out must not be nullptr");
680 (void)slot;
682}
683
684ra8_err_t ra8_rsip_kv_write(uint8_t slot, const uint8_t* in)
685{
686 RA8_CHECK_NULL_PTR(in, s_tag, "kv_write: in must not be nullptr");
687 (void)slot;
689}
690
692{
693 (void)slot;
695}
696
698{
699 RA8_CHECK_NULL_PTR(out, s_tag, "kv_count: out must not be nullptr");
701}
702
704 const uint8_t* iv,
705 const ra8_rsip_key_handle_t* src,
706 uint8_t* blob)
707{
708 RA8_CHECK_NULL_PTR(kek, s_tag, "key_wrap: kek must not be nullptr");
709 RA8_CHECK_NULL_PTR(blob, s_tag, "key_wrap: blob must not be nullptr");
710 (void)iv;
711 (void)src;
713}
714
716 const uint8_t* iv,
717 const uint8_t* blob,
719{
720 RA8_CHECK_NULL_PTR(kek, s_tag, "key_unwrap: kek must not be nullptr");
721 RA8_CHECK_NULL_PTR(dest, s_tag, "key_unwrap: dest must not be nullptr");
722 (void)iv;
723 (void)blob;
725}
726
728 const ra8_rsip_key_handle_t* ikm,
729 const uint8_t* label,
730 uint32_t label_len,
731 const uint8_t* salt,
732 uint32_t salt_len,
733 uint32_t out_len,
735{
736 RA8_CHECK_NULL_PTR(out, s_tag, "kdf: out must not be nullptr");
737 (void)op;
738 (void)ikm;
739 (void)label;
740 (void)label_len;
741 (void)salt;
742 (void)salt_len;
743 (void)out_len;
745}
746
747ra8_err_t ra8_rsip_dotf_route(uint8_t which, uint8_t slot, bool on)
748{
749 (void)which;
750 (void)slot;
751 (void)on;
753}
754
755#endif /* RA8_INSECURE_STUB_CRYPTO || RA8_OFF_TARGET */
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_RETURN_ON_ERROR(err, tag, message)
Early return on error, propagating the code upward.
Definition ra8_check.h:184
#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_not_supported
Requested feature not compiled in, not wired, or not supported by this MCU variant.
Definition ra8_err.h:180
@ k_ra8_err_invalid_arg
Invalid function argument.
Definition ra8_err.h:152
@ k_ra8_err_invalid_state
Module in wrong state for requested operation.
Definition ra8_err.h:161
@ k_ra8_ok
Success – operation completed with all postconditions satisfied.
Definition ra8_err.h:119
@ k_ra8_err_null_ptr
Pointer was NULL where a valid pointer was required.
Definition ra8_err.h:478
@ k_ra8_err_hw_error
Generic hardware fault detected (error flag set, fault interrupt).
Definition ra8_err.h:310
ra8_err_codes_t ra8_err_t
Canonical error-return type used by every ra8-firmware API.
Definition ra8_err.h:546
Lightweight Logging Interface for ra8-firmware.
ra8_err_t priv_hash_wait_done(void)
Wait for the HASH engine to raise DONE after the trailing block.
Definition ra8_rsip.c:204
Renesas Secure IP (RSIP-E50D) HAL driver – public API.
ra8_err_t ra8_rsip_kv_erase(uint8_t slot)
Zeroise a vault slot.
ra8_err_t ra8_rsip_oem_bl_version_increment(void)
Increment the OEM boot loader version (anti-rollback step).
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_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_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_kv_count(uint32_t *out)
Snapshot the populated-slot count.
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_dotf_route(uint8_t which, uint8_t slot, bool on)
Route a wrapped-key vault slot to one of the DOTF instances.
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_oem_bl_version_lock(void)
Latch the OEM_BL_LOCK so further increments are rejected.
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_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_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.
Cross-TU surface shared by the RSIP asymmetric + RSA split.
void internal_zero_handle_tail(ra8_rsip_key_handle_t *handle, uint32_t words)
Zero-fill the unused tail of a key-handle body buffer.
void internal_asym_push(ra8_rsip_off_t off, const uint8_t *buf, uint32_t len)
Stream a byte buffer into an asymmetric input lane.
void internal_asym_pull(ra8_rsip_off_t off, uint8_t *buf, uint32_t len)
Pull a byte buffer back through an asymmetric output lane.
uint8_t priv_aes_alg_byte(uint32_t alg)
Pick the AES algorithm byte that matches the wrapped key.
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)
Implementation of priv_push_bytes_to_port() – LE word stream + zero-padded tail.
uint32_t priv_handle_words_for(ra8_rsip_oem_cmd_t cmd)
Map an OEM opcode to the wrapped-key body word count.
void priv_load_handle(const ra8_rsip_key_handle_t *handle)
Stream a wrapped-key body into the engine input FIFO.
void priv_push_handle_body(const ra8_rsip_key_handle_t *handle)
Implementation of priv_push_handle_body() – KEY_STAGE body word stream.
uint32_t priv_pack_le(const uint8_t *p)
Pack 4 little-endian bytes into a uint32_t.
void priv_push_iv_lanes(ra8_rsip_off_t base, const uint8_t *iv, uint32_t iv_len)
Implementation of priv_push_iv_lanes() – bounded 4-lane LE IV window writer.
ra8_err_t priv_complete(uint32_t done_mask)
Drive a single mailbox completion (DONE poll + ack).
Cross-TU surface for the ra8_rsip driver split.
@ k_ra8_rsip_iv_words
IV / nonce register lanes.
@ k_ra8_rsip_kv_slot_w
64-byte slot = 16 * uint32_t.
@ k_ra8_rsip_byte_bits
Shift one byte.
@ k_ra8_rsip_byte_mask
Mask one byte out of a word.
@ k_ra8_rsip_byte_shift_2
Shift to high half of low word.
Renesas Secure IP (RSIP-E50D) register layout for the RA8D2.
ra8_rsip_kdf_op_t
KDF mode selector written to KDF_CTRL.
@ k_ra8_rsip_kdf_op_hkdf_sha384
HKDF SHA-384.
@ k_ra8_rsip_kdf_op_hkdf_sha512
HKDF SHA-512.
@ k_ra8_rsip_kdf_op_hkdf_sha256
HKDF SHA-256.
@ k_ra8_rsip_kw_op_wrap
Wrap a plaintext handle -> blob.
@ k_ra8_rsip_kw_op_unwrap
Unwrap a blob -> handle.
@ k_ra8_rsip_handle_words_rsa4096_priv
RSA-4096 wrapped private.
@ k_ra8_rsip_handle_words_hmac_sha256
HMAC-SHA-256 wrapped key.
@ k_ra8_rsip_dotf_on
Feed key from slot bits 31..16.
@ k_ra8_rsip_dotf_off
Disable key feed.
ra8_rsip_hash_alg_t
Algorithm selector value written to the HASH CTRL word.
@ k_ra8_rsip_hash_sha3_512
SHA3-512 FIPS PUB 202.
@ k_ra8_rsip_hash_sha512_224
SHA-512/224.
@ k_ra8_rsip_hash_shake256
SHAKE256 FIPS PUB 202.
@ k_ra8_rsip_hash_sha384
SHA-384.
@ k_ra8_rsip_hash_sha3_256
SHA3-256 FIPS PUB 202.
@ k_ra8_rsip_hash_sha256
SHA-256.
@ k_ra8_rsip_hash_sha512
SHA-512.
@ k_ra8_rsip_hash_shake128
SHAKE128 FIPS PUB 202.
@ k_ra8_rsip_hash_sha512_256
SHA-512/256.
@ k_ra8_rsip_hash_sha3_224
SHA3-224 FIPS PUB 202.
@ k_ra8_rsip_hash_sha224
SHA-224.
@ k_ra8_rsip_hash_sha3_384
SHA3-384 FIPS PUB 202.
ra8_rsip_oem_cmd_t
OEM-key install opcode written to OEM_CTRL.
@ k_ra8_rsip_oem_cmd_hmac_sha384
HMAC-SHA-384.
@ k_ra8_rsip_oem_cmd_hmac_sha512_224
HMAC-SHA-512/224.
@ k_ra8_rsip_oem_cmd_hmac_sha224
HMAC-SHA-224.
@ k_ra8_rsip_oem_cmd_hmac_sha512
HMAC-SHA-512.
@ k_ra8_rsip_oem_cmd_hmac_sha256
HMAC-SHA-256.
@ k_ra8_rsip_oem_cmd_hmac_sha512_256
HMAC-SHA-512/256.
static volatile uint32_t * ra8_rsip_reg32(ra8_rsip_off_t offset)
Volatile pointer to a 32-bit RSIP register at offset.
@ k_ra8_rsip_kv_slot_count
Number of vault slots.
@ k_ra8_rsip_trng_word_bytes
Bytes per TRNG read.
@ k_ra8_rsip_sha512_digest_bytes
SHA-512 digest length.
@ k_ra8_rsip_sha256_digest_bytes
SHA-256 digest length.
@ k_ra8_rsip_sha384_digest_bytes
SHA-384 digest length.
@ k_ra8_rsip_sha224_digest_bytes
SHA-224 digest length.
@ k_ra8_rsip_mask_isr_kv_done
ISR.KV_DONE bit.
@ k_ra8_rsip_mask_isr_done
ISR.DONE bit.
@ k_ra8_rsip_mask_isr_kdf_done
ISR.KDF_DONE bit.
ra8_rsip_kv_op_t
Key-vault command word values written to KV_CTRL.
@ k_ra8_rsip_kv_op_write
Write KV_DATA -> slot.
@ k_ra8_rsip_kv_op_read
Read slot -> KV_DATA.
@ k_ra8_rsip_kv_op_erase
Zeroise slot.
ra8_rsip_off_t
Byte offsets of every register the HAL touches.
@ k_ra8_rsip_off_kdf_len
Output length (bytes).
@ k_ra8_rsip_off_kv_data
Vault data port.
@ k_ra8_rsip_off_kv_ctrl
Vault command (read/write/erase).
@ k_ra8_rsip_off_kdf_out
Derived-key output handle.
@ k_ra8_rsip_off_hash_digest
HASH output digest base.
@ k_ra8_rsip_off_kv_count
Vault populated-slot count.
@ k_ra8_rsip_off_dotf0_ctrl
DOTF0 key route enable + slot.
@ k_ra8_rsip_off_kdf_ctrl
KDF request word.
@ k_ra8_rsip_off_hash_status
HASH ready / done flags.
@ k_ra8_rsip_off_oem_bl_lock
Lock-after-validation latch.
@ k_ra8_rsip_off_oem_bl_ver
Latched OEM BL Ver counter.
@ k_ra8_rsip_off_hash_ctrl
HASH control (algorithm select).
@ k_ra8_rsip_off_kw_iv0
Wrap IV lane 0.
@ k_ra8_rsip_off_hash_hmac
HMAC mode + key-handle slot.
@ k_ra8_rsip_off_mbox_op
Opcode written by host.
@ k_ra8_rsip_off_kw_blob_out
Wrapped-blob output lane.
@ k_ra8_rsip_off_hash_data_in
HASH input window (32-bit each).
@ k_ra8_rsip_off_kw_blob_in
Wrapped-blob input lane.
@ k_ra8_rsip_off_kv_slot
Vault slot index.
@ k_ra8_rsip_off_kdf_salt
HKDF salt lane.
@ k_ra8_rsip_off_dotf1_ctrl
DOTF1 key route enable + slot.
@ k_ra8_rsip_off_kw_kek
KEK handle slot.
@ k_ra8_rsip_off_kw_ctrl
Key-wrap command word.
@ k_ra8_rsip_off_kdf_ikm
Input keying material handle.
@ k_ra8_rsip_off_kw_handle
Source / destination handle slot.
@ k_ra8_rsip_off_kdf_label
KDF context label slot.
@ k_ra8_rsip_off_oem_bl_inc
Increment trigger (W1).
Opaque wrapped-key handle.
uint32_t body_words
Number of body words (1..261).
uint32_t body[k_ra8_rsip_handle_words_rsa4096_priv]
Wrapped body.
uint32_t alg
OEM-cmd algorithm selector.