ra8-firmware 0.1.0
Bare-metal firmware for the Renesas RA8 family (RA8D2 / RA8P1)
Loading...
Searching...
No Matches
ra8_rsip.c
Go to the documentation of this file.
1
46
47#include "ra8_rsip.h"
48
49#include <stdint.h>
50
51#include "ra8_attributes.h"
52#include "ra8_check.h"
53#include "ra8_err.h"
54#include "ra8_hw_err.h"
55#include "ra8_log.h"
56#include "ra8_mstp.h"
57#include "ra8_rsip_internal.h"
58#include "ra8_rsip_regs.h"
59
60/*
61 * Software backend selection. The RSIP-E50D HASH engine has NO documented
62 * register interface -- HUM Ch 52 "Renesas Secure IP (RSIP-E50D)" is a 6-page
63 * feature overview (p 3302-3307) with no register map -- and the hand-written
64 * register I/O path is NON-FUNCTIONAL on silicon: verified on the EK-RA8D2, the
65 * RSIP registers read all-zero, writes do not stick, and ra8_rsip_sha256 returns
66 * k_ra8_err_hw_timeout with a zero digest (see
67 * examples/ek_ra8d2/hil_needs_revalidation/rsip_sha256_kat). Renesas drives the RSIP through
68 * FSP's opaque procedural "primitive" sequences, not registers. Until that FSP
69 * driver is ported, the software SHA-256 is the ONLY working backend, so it is
70 * enabled unconditionally. The register-sequence model is retained (never
71 * compiled) behind RA8_RSIP_HASH_HARDWARE as a reference for the future port and
72 * for the host register-plumbing tests, which drive it against ra8_fake_mmap.
73 */
74#ifndef RA8_RSIP_SOFTWARE_BACKEND
76#define RA8_RSIP_SOFTWARE_BACKEND (1)
77#endif
78
79static void internal_sw_sha256(const uint8_t* msg, uint32_t msg_len, uint8_t* digest);
80
92static const char* s_tag = "RSIP";
93
108
117static void* s_rsip_ctx;
118
121{
122 volatile const uint32_t* reg = ra8_rsip_reg32(offset);
123 for (uint32_t i = 0U; i < k_ra8_rsip_poll_budget; ++i) {
124#if defined(RA8_OFF_TARGET) && defined(UNIT_TEST)
125 /* Host unit-test MMIO wait seam (tests/mocks/src/ra8_fake_mmio.c): an unarmed
126 * register satisfies the wait on its first poll; a test arms fail_wait /
127 * satisfy_after to drive the timeout / continuation legs of this loop. */
128 if (ra8_fake_mmio_wait_eval(reg, i, ((*reg & mask) == mask))) {
129 return k_ra8_ok;
130 }
131#else
132 if ((*reg & mask) == mask) {
133 return k_ra8_ok;
134 }
135#endif
136 }
138}
139
167{
168 volatile uint32_t* ctrl = ra8_rsip_reg32(k_ra8_rsip_off_ctrl);
169
170 /* HUM Ch 52.1 "Overview" p 3302 */
171 /* Engine self-test gate. */
173
175 if (err != k_ra8_ok) {
177 }
178
179 /* HUM Ch 52.1 "Overview" p 3302 */
180 /* BIST is a one-shot trigger; clear it post-pass so CTRL leaves
181 * only ENABLE asserted. Leaving BIST=1 would re-arm the self-test
182 * sequencer on the next CTRL write on real silicon. */
184
185 return k_ra8_ok;
186}
187
188#ifdef RA8_RSIP_HASH_HARDWARE /* retained RSIP HASH model, never compiled (see note above) */
189
190/* Stream the SHA-256 message body into the HASH input port -- see surrounding code and HUM citations. */
192static void internal_sha256_push_msg(const uint8_t* msg, uint32_t msg_len)
193{
194 /* HUM Ch 52.2.3 "Hash Generator" p 3306 */
195 /* Stream message into HASH input port one 32-bit word at a time.
196 * The HAL handles partial trailing bytes by zero-extending into
197 * a single word. */
199}
200
201#endif /* RA8_RSIP_HASH_HARDWARE */
202
203/* priv_hash_wait_done stays compiled: it is shared with ra8_rsip_asym.c. */
205{
206 /* On hardware the engine raises HASH_STATUS.DONE once it absorbs the
207 * trailing block + length; the bounded wait routes through the host
208 * ra8_fake_mmio seam inside priv_wait_bit. */
210}
211
212#ifdef RA8_RSIP_HASH_HARDWARE
213
214/* Read 8 SHA-256 digest words and ack the DONE bit -- see surrounding code and HUM citations. */
216static void internal_sha256_pull_digest(uint8_t* digest)
217{
218 /* HUM Ch 52.2.3 "Hash Generator" p 3306 */
219 /* Read 8 digest words. */
220 for (uint32_t w = 0U; w < (uint32_t)k_ra8_rsip_sha256_digest_words; ++w) {
221 /* Computed digest-word offset is a valid HUM-defined register location,
222 * not a literal enumerator -- the analyzer can't see that. */
223 const ra8_rsip_off_t off =
225 const uint32_t word = *ra8_rsip_reg32(off);
226 priv_unpack_le(word, &digest[w << k_ra8_rsip_word_shift]);
227 }
228 /* Ack the DONE bit so the next call starts clean. */
230}
231
232#endif /* RA8_RSIP_HASH_HARDWARE */
233
235{
236 RA8_CHECK_NULL_PTR(cfg, s_tag, "cfg must not be nullptr");
237
238 /* HUM Ch 11.2.8 "MSTPCRC : Module Stop Control Register C" p 446 */
239 /* HUM Ch 52.3.2 "Module-Stop Function Setting" p 3307 */
241 /* GCOVR_EXCL_BR_START -- MSTP HW readback */
242 RA8_RETURN_ON_ERROR(mst_err, s_tag, "rsip_init: mstp enable");
243 /* GCOVR_EXCL_BR_STOP */
244
245 /* HUM Ch 52.1 "Overview" p 3302 */
246 /* Engine reset + enable mailbox. */
247 volatile uint32_t* ctrl = ra8_rsip_reg32(k_ra8_rsip_off_ctrl);
250
251 if (cfg->run_bist) {
252 const ra8_err_t bist_err = internal_run_bist();
253 if (bist_err != k_ra8_ok) {
255 return bist_err;
256 }
257 }
258
259 /* HUM Ch 52.1 "Overview" p 3302 */
260 /* Ack any pending IRQ bits. */
262
263 ra8_log_info(s_tag, "rsip_init");
264 return k_ra8_ok;
265}
266
268{
269 /* HUM Ch 52.3.1 "Software Standby Mode" p 3307 */
270 /* Clear ENABLE before gating. */
272
273 /* HUM Ch 52.1 "Overview" p 3302 */
274 /* Scrub pending IRQ flags. */
276
277 s_rsip_fn = nullptr;
278 s_rsip_ctx = nullptr;
279
280 /* HUM Ch 11.2.8 "MSTPCRC : Module Stop Control Register C" p 446 */
282}
283
285{
286 RA8_CHECK_NULL_PTR(out, s_tag, "out must not be nullptr");
287 /* HUM Ch 52.1 "Overview" p 3302 */
288 /* Mailbox STATUS read. */
290 return k_ra8_ok;
291}
292
294{
295 if ((mask & ~k_ra8_rsip_mask_isr_all) != 0U) {
297 }
298 if (mask == 0U) {
300 }
301 /* HUM Ch 52.1 "Overview" p 3302 */
302 /* W1C ack on the ISR word. */
304 return k_ra8_ok;
305}
306
308{
309 s_rsip_fn = fn;
310 s_rsip_ctx = ctx;
311 return k_ra8_ok;
312}
313
316{
317 /* HUM Ch 52.1 "Overview" p 3302 */
318 /* Snapshot then ack the ISR. */
319 volatile uint32_t* isr = ra8_rsip_reg32(k_ra8_rsip_off_isr);
320 const uint32_t snapshot = *isr;
321 if (snapshot == 0U) {
322 return;
323 }
325 void* const ctx = s_rsip_ctx;
326 /* W1C ack: writing the snapshot back clears each pending bit on real
327 * hardware. The host-test RAM backing has no W1C semantics, so a test
328 * that needs the post-ack state stages the ISR word itself. */
329 *isr = snapshot;
330 if (fn != nullptr) {
331 fn(ctx, snapshot);
332 }
333}
334
335// `buf` is an output the RA8_RSIP_TRNG_HARDWARE path fills; the fail-closed build
336// writes nothing, so clang-tidy cannot see a write and wrongly wants it const.
337// NOLINTNEXTLINE(readability-non-const-parameter) -- buf is filled only by the RA8_RSIP_TRNG_HARDWARE path; the fail-closed build writes nothing.
338ra8_err_t ra8_rsip_trng_read(uint8_t* buf, uint32_t len)
339{
340 RA8_CHECK_NULL_PTR(buf, s_tag, "buf must not be nullptr");
341 if (len == 0U) {
343 }
344 if ((len & ((uint32_t)k_ra8_rsip_trng_word_bytes - 1U)) != 0U) {
346 }
347
348#ifdef RA8_RSIP_TRNG_HARDWARE
349 volatile uint32_t* status = ra8_rsip_reg32(k_ra8_rsip_off_rnd_status);
350 volatile const uint32_t* data = ra8_rsip_reg32(k_ra8_rsip_off_rnd_data);
351
352 /* HUM Ch 52.1 "Overview" p 3302 */
353 /* Arm TRNG control word. */
355
356 const uint32_t words = len >> k_ra8_rsip_word_shift;
357 for (uint32_t w = 0U; w < words; ++w) {
358 /* On hardware the engine asserts READY when a fresh word is
359 * available. The host fake has no producer thread, so we
360 * pre-assert and re-assert each iteration to keep the spin
361 * deterministic. */
363
364 const ra8_err_t wait_err =
366 if (wait_err != k_ra8_ok) {
367 return wait_err;
368 }
369
370 const uint32_t word = *data;
371 /* HUM Ch 52.1 "Overview" p 3302 */
372 /* TRNG output is little-endian. */
373 buf[(w << k_ra8_rsip_word_shift) + 0U] = (uint8_t)(word & k_ra8_rsip_byte_mask);
374 buf[(w << k_ra8_rsip_word_shift) + 1U] =
375 (uint8_t)((word >> k_ra8_rsip_byte_bits) & k_ra8_rsip_byte_mask);
376 buf[(w << k_ra8_rsip_word_shift) + 2U] =
377 (uint8_t)((word >> k_ra8_rsip_byte_shift_2) & k_ra8_rsip_byte_mask);
378 buf[(w << k_ra8_rsip_word_shift) + 3U] =
379 (uint8_t)((word >> k_ra8_rsip_byte_shift_3) & k_ra8_rsip_byte_mask);
380
381 /* Clear READY so the next iteration genuinely waits. */
383 }
384 return k_ra8_ok;
385#else
386 /* The RSIP-E50D TRNG has no documented register interface (HUM Ch 52 is a
387 * 6-page feature overview with no register map); the `RND_*` offsets above
388 * are invented and do not work on silicon -- the READY bit never asserts.
389 * Fail closed with a clear status rather than spin to a timeout or, worse,
390 * hand back an all-zero or deterministic value: predictable "entropy" is far
391 * more dangerous than an honest error. A real TRNG needs an FSP-derived
392 * RSIP primitive sequence; a software PRNG is NOT a substitute here. */
394#endif
395}
396
397ra8_err_t ra8_rsip_sha256(const uint8_t* msg, uint32_t msg_len, uint8_t* digest)
398{
399 RA8_CHECK_NULL_PTR(msg, s_tag, "msg must not be nullptr");
400 RA8_CHECK_NULL_PTR(digest, s_tag, "digest must not be nullptr");
401
402#ifdef RA8_RSIP_HASH_HARDWARE
403 /* HUM Ch 52.2.3 "Hash Generator" p 3306 */
404 /* Real silicon command-issue sequence (NON-FUNCTIONAL on this silicon; never
405 * compiled -- see the backend note near the top of the file):
406 * 1. poll HASH_STATUS.READY (engine quiescent);
407 * 2. write algorithm selector to HASH_CTRL;
408 * 3. stream message words through HASH_DATA_IN;
409 * 4. spin on HASH_STATUS.DONE;
410 * 5. drain 8 digest words from HASH_DIGEST. */
412 const ra8_err_t ready_err =
414 RA8_RETURN_ON_ERROR(ready_err, s_tag, "rsip_sha256: hash ready");
415
416 /* HASH algorithm select. */
418
419 internal_sha256_push_msg(msg, msg_len);
420
421 const ra8_err_t wait_err = priv_hash_wait_done();
422 RA8_RETURN_ON_ERROR(wait_err, s_tag, "rsip_sha256: hash done");
423
424 internal_sha256_pull_digest(digest);
425 return k_ra8_ok;
426#else
427 /* The RSIP HASH hardware has no usable register interface, so compute the
428 * digest in software. This is the path used on silicon and on the host; it is
429 * what makes ra8_rot's on-silicon image digest work. */
430 internal_sw_sha256(msg, msg_len, digest);
431 return k_ra8_ok;
432#endif
433}
434
435/* =============================================================================
436 * SHA-256 incremental
437 * =============================================================================
438 */
439
440#ifdef RA8_RSIP_SOFTWARE_BACKEND
441
474
475/* 32-bit right-rotate -- see surrounding code and HUM citations. */
477static inline uint32_t internal_sw_rotr(uint32_t x, uint32_t n)
478{
479 return (x >> n) | (x << (k_ra8_rsip_sw_word_bits - n));
480}
481
482// clang-format off: FIPS 180-4 K[0..63] table, four constants per row.
490 0x428a2f98UL, 0x71374491UL, 0xb5c0fbcfUL, 0xe9b5dba5UL,
491 0x3956c25bUL, 0x59f111f1UL, 0x923f82a4UL, 0xab1c5ed5UL,
492 0xd807aa98UL, 0x12835b01UL, 0x243185beUL, 0x550c7dc3UL,
493 0x72be5d74UL, 0x80deb1feUL, 0x9bdc06a7UL, 0xc19bf174UL,
494 0xe49b69c1UL, 0xefbe4786UL, 0x0fc19dc6UL, 0x240ca1ccUL,
495 0x2de92c6fUL, 0x4a7484aaUL, 0x5cb0a9dcUL, 0x76f988daUL,
496 0x983e5152UL, 0xa831c66dUL, 0xb00327c8UL, 0xbf597fc7UL,
497 0xc6e00bf3UL, 0xd5a79147UL, 0x06ca6351UL, 0x14292967UL,
498 0x27b70a85UL, 0x2e1b2138UL, 0x4d2c6dfcUL, 0x53380d13UL,
499 0x650a7354UL, 0x766a0abbUL, 0x81c2c92eUL, 0x92722c85UL,
500 0xa2bfe8a1UL, 0xa81a664bUL, 0xc24b8b70UL, 0xc76c51a3UL,
501 0xd192e819UL, 0xd6990624UL, 0xf40e3585UL, 0x106aa070UL,
502 0x19a4c116UL, 0x1e376c08UL, 0x2748774cUL, 0x34b0bcb5UL,
503 0x391c0cb3UL, 0x4ed8aa4aUL, 0x5b9cca4fUL, 0x682e6ff3UL,
504 0x748f82eeUL, 0x78a5636fUL, 0x84c87814UL, 0x8cc70208UL,
505 0x90befffaUL, 0xa4506cebUL, 0xbef9a3f7UL, 0xc67178f2UL,
506};
507
515 0x6a09e667UL, 0xbb67ae85UL, 0x3c6ef372UL, 0xa54ff53aUL,
516 0x510e527fUL, 0x9b05688cUL, 0x1f83d9abUL, 0x5be0cd19UL,
517};
518// clang-format on
519
520/* Build the 64-word SHA-256 message schedule from a 64-byte block -- see surrounding code and HUM citations. */
523 const uint8_t block[k_ra8_rsip_sha256_block])
524{
525 for (uint32_t i = 0U; i < k_ra8_rsip_sw_sha256_block_w; ++i) {
526 const size_t base = (size_t)i * (size_t)k_ra8_rsip_trng_word_bytes;
527 w[i] = ((uint32_t)block[base] << k_ra8_rsip_byte_shift_3) |
528 ((uint32_t)block[base + 1U] << k_ra8_rsip_byte_shift_2) |
529 ((uint32_t)block[base + 2U] << k_ra8_rsip_byte_bits) | (uint32_t)block[base + 3U];
530 }
532 const uint32_t back15 = w[i - k_ra8_rsip_sw_sha256_w_back_15];
533 const uint32_t back2 = w[i - k_ra8_rsip_sw_sha256_w_back_2];
534 const uint32_t s0 = internal_sw_rotr(back15, k_ra8_rsip_sw_rotr_7) ^
536 (back15 >> k_ra8_rsip_sw_rotr_3);
537 const uint32_t s1 = internal_sw_rotr(back2, k_ra8_rsip_sw_rotr_17) ^
539 (back2 >> k_ra8_rsip_sw_rotr_10);
540 w[i] = w[i - k_ra8_rsip_sw_sha256_w_back_16] + s0 + w[i - k_ra8_rsip_sw_sha256_w_back_7] + s1;
541 }
542}
543
544/* 64-round SHA-256 main loop running on an a -- see surrounding code and HUM citations. */
556
579 const uint32_t w[k_ra8_rsip_sw_sha256_round_cnt])
580{
581 /* FIPS PUB 180-4 Section 6.2.2: a..h working-state lanes are spec-named
582 * indices 0..7 of the 8-word hash state, not arbitrary literals. */
583 uint32_t a = s[k_sha256_lane_a];
584 uint32_t b = s[k_sha256_lane_b];
585 uint32_t c = s[k_sha256_lane_c];
586 uint32_t d = s[k_sha256_lane_d];
587 uint32_t e = s[k_sha256_lane_e];
588 uint32_t f = s[k_sha256_lane_f];
589 uint32_t g = s[k_sha256_lane_g];
590 uint32_t h = s[k_sha256_lane_h];
591 for (uint32_t i = 0U; i < k_ra8_rsip_sw_sha256_round_cnt; ++i) {
592 const uint32_t s1 = internal_sw_rotr(e, k_ra8_rsip_sw_rotr_6) ^
595 const uint32_t ch = (e & f) ^ ((~e) & g);
596 const uint32_t temp1 = h + s1 + ch + s_sw_sha256_k[i] + w[i];
597 const uint32_t s0 = internal_sw_rotr(a, k_ra8_rsip_sw_rotr_2) ^
600 const uint32_t maj = (a & b) ^ (a & c) ^ (b & c);
601 const uint32_t temp2 = s0 + maj;
602 h = g;
603 g = f;
604 f = e;
605 e = d + temp1;
606 d = c;
607 c = b;
608 b = a;
609 a = temp1 + temp2;
610 }
611 s[k_sha256_lane_a] = a;
612 s[k_sha256_lane_b] = b;
613 s[k_sha256_lane_c] = c;
614 s[k_sha256_lane_d] = d;
615 s[k_sha256_lane_e] = e;
616 s[k_sha256_lane_f] = f;
617 s[k_sha256_lane_g] = g;
618 s[k_sha256_lane_h] = h;
619}
620
621/* Run a single 64-byte SHA-256 compression block -- see surrounding code and HUM citations. */
624 const uint8_t block[k_ra8_rsip_sha256_block])
625{
628
629 uint32_t working[k_ra8_rsip_sw_sha256_state_w];
630 for (uint32_t i = 0U; i < k_ra8_rsip_sw_sha256_state_w; ++i) {
631 working[i] = state[i];
632 }
633 internal_sw_sha256_rounds(working, w);
634 for (uint32_t i = 0U; i < k_ra8_rsip_sw_sha256_state_w; ++i) {
635 state[i] += working[i];
636 }
637}
638
658{
659 const uint64_t bit_len = ctx->total_bytes * (uint64_t)k_ra8_rsip_byte_bits;
660 ctx->block[ctx->used++] = (uint8_t)k_ra8_rsip_sw_sha256_pad_byte;
662 while (ctx->used < k_ra8_rsip_sha256_block) {
663 ctx->block[ctx->used++] = 0U;
664 }
666 ctx->used = 0U;
667 }
668 while (ctx->used < ((uint32_t)k_ra8_rsip_sha256_block - k_ra8_rsip_sw_sha256_len_bytes)) {
669 ctx->block[ctx->used++] = 0U;
670 }
671 for (uint32_t b = 0U; b < k_ra8_rsip_sw_sha256_len_bytes; ++b) {
672 const uint32_t shift = (k_ra8_rsip_sw_sha256_len_bytes - 1U - b) * k_ra8_rsip_byte_bits;
674 (uint8_t)((bit_len >> shift) & (uint64_t)k_ra8_rsip_byte_mask);
675 }
677}
678
679/* Emit a big-endian 32-byte SHA-256 digest from working state -- see surrounding code and HUM citations. */
682 uint8_t* digest)
683{
684 for (uint32_t w = 0U; w < k_ra8_rsip_sw_sha256_state_w; ++w) {
685 const size_t base = (size_t)w * (size_t)k_ra8_rsip_trng_word_bytes;
686 digest[base + 0U] = (uint8_t)((state[w] >> k_ra8_rsip_byte_shift_3) & k_ra8_rsip_byte_mask);
687 digest[base + 1U] = (uint8_t)((state[w] >> k_ra8_rsip_byte_shift_2) & k_ra8_rsip_byte_mask);
688 digest[base + 2U] = (uint8_t)((state[w] >> k_ra8_rsip_byte_bits) & k_ra8_rsip_byte_mask);
689 digest[base + 3U] = (uint8_t)(state[w] & k_ra8_rsip_byte_mask);
690 }
691}
692
693/* One-shot software SHA-256 over a contiguous buffer -- see surrounding code and HUM citations. */
724static void internal_sw_sha256(const uint8_t* msg, uint32_t msg_len, uint8_t* digest)
725{
726 ra8_rsip_sha256_ctx_t ctx = {};
727 (void)ra8_rsip_sha256_init(&ctx);
728 (void)ra8_rsip_sha256_update(&ctx, msg, msg_len);
729 (void)ra8_rsip_sha256_final(&ctx, digest);
730}
731
732#endif /* RA8_RSIP_SOFTWARE_BACKEND */
733
734/* Compute SHA-256 of a buffer routed by the active backend -- see surrounding code and HUM citations. */
736static ra8_err_t internal_sha256_dispatch(const uint8_t* msg, uint32_t msg_len, uint8_t* digest)
737{
738#ifdef RA8_RSIP_SOFTWARE_BACKEND
739 internal_sw_sha256(msg, msg_len, digest);
740 return k_ra8_ok;
741#else
742 static const uint8_t s_empty = 0U;
743 return ra8_rsip_sha256((msg == nullptr) ? &s_empty : msg, msg_len, digest);
744#endif
745}
746
748{
749 RA8_CHECK_NULL_PTR(ctx, s_tag, "ctx must not be nullptr");
750 for (uint32_t i = 0U; i < k_ra8_rsip_sha256_state_words; ++i) {
751 ctx->state[i] = s_sw_sha256_h0[i];
752 }
753 ctx->used = 0U;
754 ctx->total_bytes = 0U;
755 ctx->initialized = 1U;
756 return k_ra8_ok;
757}
758
759ra8_err_t ra8_rsip_sha256_update(ra8_rsip_sha256_ctx_t* ctx, const uint8_t* data, uint32_t len)
760{
761 RA8_CHECK_NULL_PTR(ctx, s_tag, "ctx must not be nullptr");
762 if ((data == nullptr) && (len != 0U)) {
763 return k_ra8_err_null_ptr;
764 }
765 if (ctx->initialized != 1U) {
767 }
768 if (len == 0U) {
769 return k_ra8_ok;
770 }
771 const uint64_t max_bytes = UINT64_MAX / (uint64_t)k_ra8_rsip_byte_bits;
772 if ((ctx->total_bytes > max_bytes) || ((uint64_t)len > (max_bytes - ctx->total_bytes))) {
774 }
775 uint32_t consumed = 0U;
776 while ((ctx->used != 0U) && (consumed < len)) {
777 ctx->block[ctx->used++] = data[consumed++];
778 if (ctx->used == k_ra8_rsip_sha256_block) {
780 ctx->used = 0U;
781 }
782 }
783 while ((len - consumed) >= k_ra8_rsip_sha256_block) {
784 internal_sw_sha256_compress(ctx->state, &data[consumed]);
785 consumed += k_ra8_rsip_sha256_block;
786 }
787 while (consumed < len) {
788 ctx->block[ctx->used++] = data[consumed++];
789 }
790 ctx->total_bytes += len;
791 return k_ra8_ok;
792}
793
795{
796 RA8_CHECK_NULL_PTR(ctx, s_tag, "ctx must not be nullptr");
797 RA8_CHECK_NULL_PTR(digest_out, s_tag, "digest_out must not be nullptr");
798 if (ctx->initialized != 1U) {
800 }
802 internal_sw_sha256_emit(ctx->state, digest_out);
803 for (uint32_t i = 0U; i < k_ra8_rsip_sha256_state_words; ++i) {
804 ctx->state[i] = 0U;
805 }
806 for (uint32_t i = 0U; i < k_ra8_rsip_sha256_block; ++i) {
807 ctx->block[i] = 0U;
808 }
809 ctx->total_bytes = 0U;
810 ctx->used = 0U;
811 ctx->initialized = 0U;
812 return k_ra8_ok;
813}
814
815/* =============================================================================
816 * HMAC-SHA-256 incremental
817 * =============================================================================
818 */
819
820/* Build the 64-byte HMAC key block per RFC 2104 Section 2 -- see surrounding code and HUM citations. */
822static ra8_err_t
823internal_hmac_prep_key(const uint8_t* key, uint32_t key_len, uint8_t block[k_ra8_rsip_sha256_block])
824{
825 for (uint32_t i = 0U; i < k_ra8_rsip_sha256_block; ++i) {
826 block[i] = 0x00U;
827 }
828 if (key_len > k_ra8_rsip_sha256_block) {
829 uint8_t digest[k_ra8_rsip_sha256_digest_bytes] = {};
830 const ra8_err_t err = internal_sha256_dispatch(key, key_len, digest);
831 if (err != k_ra8_ok) {
832 return err;
833 }
834 for (uint32_t i = 0U; i < k_ra8_rsip_sha256_digest_bytes; ++i) {
835 block[i] = digest[i];
836 }
837 } else if (key_len > 0U) {
838 for (uint32_t i = 0U; i < key_len; ++i) {
839 block[i] = key[i];
840 }
841 }
842 return k_ra8_ok;
843}
844
846ra8_rsip_hmac_sha256_init(ra8_rsip_hmac_sha256_ctx_t* ctx, const uint8_t* key, uint32_t key_len)
847{
848 RA8_CHECK_NULL_PTR(ctx, s_tag, "ctx must not be nullptr");
849 if ((key == nullptr) && (key_len != 0U)) {
850 return k_ra8_err_null_ptr;
851 }
852 const ra8_err_t prep_err = internal_hmac_prep_key(key, key_len, ctx->key_block);
853 if (prep_err != k_ra8_ok) {
854 return prep_err;
855 }
856 const ra8_err_t init_err = ra8_rsip_sha256_init(&ctx->inner);
857 if (init_err != k_ra8_ok) {
858 return init_err;
859 }
860 uint8_t ipad[k_ra8_rsip_sha256_block];
861 for (uint32_t i = 0U; i < k_ra8_rsip_sha256_block; ++i) {
862 ipad[i] = ctx->key_block[i] ^ (uint8_t)k_ra8_rsip_hmac_inner_pad;
863 }
865 if (upd_err != k_ra8_ok) {
866 ctx->inner.initialized = 0U;
867 return upd_err;
868 }
869 ctx->initialized = 1U;
870 return k_ra8_ok;
871}
872
874ra8_rsip_hmac_sha256_update(ra8_rsip_hmac_sha256_ctx_t* ctx, const uint8_t* data, uint32_t len)
875{
876 RA8_CHECK_NULL_PTR(ctx, s_tag, "ctx must not be nullptr");
877 if (ctx->initialized != 1U) {
879 }
880 return ra8_rsip_sha256_update(&ctx->inner, data, len);
881}
882
911 const uint8_t inner[k_ra8_rsip_sha256_digest_bytes],
912 uint8_t* mac_out)
913{
914 uint8_t outer_buf[(size_t)k_ra8_rsip_sha256_block + (size_t)k_ra8_rsip_sha256_digest_bytes];
915 for (uint32_t i = 0U; i < k_ra8_rsip_sha256_block; ++i) {
916 outer_buf[i] = key_block[i] ^ (uint8_t)k_ra8_rsip_hmac_outer_pad;
917 }
918 for (uint32_t i = 0U; i < k_ra8_rsip_sha256_digest_bytes; ++i) {
919 outer_buf[k_ra8_rsip_sha256_block + i] = inner[i];
920 }
921 return internal_sha256_dispatch(outer_buf,
924 mac_out);
925}
926
928{
929 RA8_CHECK_NULL_PTR(ctx, s_tag, "ctx must not be nullptr");
930 RA8_CHECK_NULL_PTR(mac_out, s_tag, "mac_out must not be nullptr");
931 if (ctx->initialized != 1U) {
933 }
934 uint8_t inner_digest[k_ra8_rsip_sha256_digest_bytes] = {};
935 const ra8_err_t inner_err = ra8_rsip_sha256_final(&ctx->inner, inner_digest);
936 ra8_err_t result = inner_err;
937 if (inner_err == k_ra8_ok) {
938 result = internal_hmac_outer(ctx->key_block, inner_digest, mac_out);
939 }
940 ctx->initialized = 0U;
941 for (uint32_t i = 0U; i < k_ra8_rsip_sha256_block; ++i) {
942 ctx->key_block[i] = 0x00U;
943 }
944 return result;
945}
946
948{
949 /* HUM Ch 52.3.1 "Software Standby Mode" p 3307 */
950 /* Engine MUST be idle before standby. Clear ENABLE then gate. */
953}
954
956{
957 /* HUM Ch 11.2.8 "MSTPCRC : Module Stop Control Register C" p 446 */
959 /* GCOVR_EXCL_BR_START -- MSTP HW readback */
960 RA8_RETURN_ON_ERROR(mst_err, s_tag, "rsip_exit_stop: mstp enable");
961 /* GCOVR_EXCL_BR_STOP */
962
963 /* HUM Ch 52.1 "Overview" p 3302 */
964 /* Engine re-enable then BIST. */
966
967 const ra8_err_t bist_err = internal_run_bist();
968 if (bist_err != k_ra8_ok) {
970 return bist_err;
971 }
972 return k_ra8_ok;
973}
static const char * s_tag
Logging / check tag.
Definition ra8_app.c:17
Annotation-attribute framework macros for ra8-firmware.
#define RA8_ISR_SAFE
The function is callable from interrupt context.
#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_hw_init_failed
Hardware peripheral failed to initialise.
Definition ra8_err.h:290
@ 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_err_hw_timeout
Hardware timed out waiting for a flag or handshake.
Definition ra8_err.h:304
@ 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_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
Bounded wait-flag primitives for RA8D2 HAL drivers.
Lightweight Logging Interface for ra8-firmware.
#define ra8_log_info(tag, message)
RA8 log info.
Definition ra8_log.h:364
Ref-counted Module Stop Control wrapper for the RA8D2.
ra8_err_t ra8_mstp_enable(ra8_mstp_t id)
Reference-counted "ungate this peripheral" request.
Definition ra8_mstp.c:343
ra8_err_t ra8_mstp_disable(ra8_mstp_t id)
Reference-counted "gate this peripheral" request.
Definition ra8_mstp.c:382
@ k_ra8_mstp_rsip
MSTPC31 RSIP-E50D.
static void internal_sw_sha256_emit(const uint32_t state[k_ra8_rsip_sw_sha256_state_w], uint8_t *digest)
Definition ra8_rsip.c:681
ra8_err_t ra8_rsip_hmac_sha256_final(ra8_rsip_hmac_sha256_ctx_t *ctx, uint8_t *mac_out)
Emit the MAC of a streaming HMAC-SHA-256 context.
Definition ra8_rsip.c:927
static const uint32_t s_sw_sha256_k[k_ra8_rsip_sw_sha256_round_cnt]
FIPS PUB 180-4 Section 4.1.2 SHA-256 round constants K[0..63].
Definition ra8_rsip.c:489
ra8_err_t ra8_rsip_get_status(uint32_t *out)
Snapshot the STATUS mailbox word.
Definition ra8_rsip.c:284
ra8_err_t ra8_rsip_enter_stop(void)
Park the engine for software-standby entry.
Definition ra8_rsip.c:947
ra8_err_t priv_wait_bit(ra8_rsip_off_t offset, uint32_t mask)
Implementation of priv_wait_bit() – bounded MMIO mask spin.
Definition ra8_rsip.c:120
ra8_err_t ra8_rsip_sha256_final(ra8_rsip_sha256_ctx_t *ctx, uint8_t *digest_out)
Emit the digest of a streaming SHA-256 context.
Definition ra8_rsip.c:794
static void * s_rsip_ctx
Caller context paired with s_rsip_fn.
Definition ra8_rsip.c:117
ra8_err_t ra8_rsip_deinit(void)
Power off the RSIP engine.
Definition ra8_rsip.c:267
static void internal_sw_sha256_compress(uint32_t state[k_ra8_rsip_sw_sha256_state_w], const uint8_t block[k_ra8_rsip_sha256_block])
Definition ra8_rsip.c:623
ra8_err_t ra8_rsip_hmac_sha256_update(ra8_rsip_hmac_sha256_ctx_t *ctx, const uint8_t *data, uint32_t len)
Absorb additional bytes into a streaming HMAC-SHA-256 context.
Definition ra8_rsip.c:874
ra8_rsip_sw_sha256_t
File-private constants for the software SHA-256 fall-back.
Definition ra8_rsip.c:450
@ k_ra8_rsip_sw_sha256_round_cnt
Sched + compression rounds.
Definition ra8_rsip.c:452
@ k_ra8_rsip_sw_rotr_19
RA8 rsip sw rotr 19.
Definition ra8_rsip.c:469
@ k_ra8_rsip_sw_sha256_pad_byte
RFC 6234 / FIPS 180-4 marker.
Definition ra8_rsip.c:455
@ k_ra8_rsip_sw_sha256_w_back_2
W[i-2] schedule lookback.
Definition ra8_rsip.c:456
@ k_ra8_rsip_sw_rotr_22
RA8 rsip sw rotr 22.
Definition ra8_rsip.c:470
@ k_ra8_rsip_sw_sha256_w_back_7
W[i-7] schedule lookback.
Definition ra8_rsip.c:457
@ k_ra8_rsip_sw_rotr_6
RA8 rsip sw rotr 6.
Definition ra8_rsip.c:462
@ k_ra8_rsip_sw_rotr_18
RA8 rsip sw rotr 18.
Definition ra8_rsip.c:468
@ k_ra8_rsip_sw_rotr_7
RA8 rsip sw rotr 7.
Definition ra8_rsip.c:463
@ k_ra8_rsip_sw_sha256_w_back_16
W[i-16] schedule lookback.
Definition ra8_rsip.c:459
@ k_ra8_rsip_sw_sha256_state_w
8 working-state words.
Definition ra8_rsip.c:453
@ k_ra8_rsip_sw_rotr_11
RA8 rsip sw rotr 11.
Definition ra8_rsip.c:465
@ k_ra8_rsip_sw_word_bits
Word width in bits.
Definition ra8_rsip.c:472
@ k_ra8_rsip_sw_rotr_10
RA8 rsip sw rotr 10.
Definition ra8_rsip.c:464
@ k_ra8_rsip_sw_rotr_13
RA8 rsip sw rotr 13.
Definition ra8_rsip.c:466
@ k_ra8_rsip_sw_rotr_25
RA8 rsip sw rotr 25.
Definition ra8_rsip.c:471
@ k_ra8_rsip_sw_sha256_block_w
64-byte block = 16 words.
Definition ra8_rsip.c:451
@ k_ra8_rsip_sw_rotr_17
RA8 rsip sw rotr 17.
Definition ra8_rsip.c:467
@ k_ra8_rsip_sw_sha256_len_bytes
64-bit length encoding tail.
Definition ra8_rsip.c:454
@ k_ra8_rsip_sw_rotr_3
RA8 rsip sw rotr 3.
Definition ra8_rsip.c:461
@ k_ra8_rsip_sw_sha256_w_back_15
W[i-15] schedule lookback.
Definition ra8_rsip.c:458
@ k_ra8_rsip_sw_rotr_2
RA8 rsip sw rotr 2.
Definition ra8_rsip.c:460
static ra8_err_t internal_sha256_dispatch(const uint8_t *msg, uint32_t msg_len, uint8_t *digest)
Definition ra8_rsip.c:736
static uint32_t internal_sw_rotr(uint32_t x, uint32_t n)
Definition ra8_rsip.c:477
ra8_err_t ra8_rsip_init(const ra8_rsip_config_t *cfg)
Power on the RSIP engine and (optionally) run BIST.
Definition ra8_rsip.c:234
ra8_err_t ra8_rsip_clear_status(uint32_t mask)
Acknowledge ISR bits via write-1-to-clear.
Definition ra8_rsip.c:293
ra8_err_t ra8_rsip_hmac_sha256_init(ra8_rsip_hmac_sha256_ctx_t *ctx, const uint8_t *key, uint32_t key_len)
Initialise a streaming HMAC-SHA-256 context.
Definition ra8_rsip.c:846
static void internal_sw_sha256_finalize(ra8_rsip_sha256_ctx_t *ctx)
Finalize one streaming SHA-256 chaining state.
Definition ra8_rsip.c:657
ra8_err_t ra8_rsip_sha256_update(ra8_rsip_sha256_ctx_t *ctx, const uint8_t *data, uint32_t len)
Absorb additional bytes into a streaming SHA-256 context.
Definition ra8_rsip.c:759
ra8_err_t ra8_rsip_exit_stop(void)
Re-enable the engine after software-standby exit.
Definition ra8_rsip.c:955
static ra8_err_t internal_hmac_prep_key(const uint8_t *key, uint32_t key_len, uint8_t block[k_ra8_rsip_sha256_block])
Definition ra8_rsip.c:823
static void internal_sw_sha256(const uint8_t *msg, uint32_t msg_len, uint8_t *digest)
One-shot software SHA-256 over a contiguous message buffer.
Definition ra8_rsip.c:724
ra8_err_t ra8_rsip_trng_read(uint8_t *buf, uint32_t len)
Drain len bytes from the RSIP true RNG – fail-closed, no backend.
Definition ra8_rsip.c:338
void ra8_rsip_dispatch(void)
Run the attached callback with the current ISR snapshot.
Definition ra8_rsip.c:315
static void internal_sw_sha256_rounds(uint32_t s[k_ra8_rsip_sw_sha256_state_w], const uint32_t w[k_ra8_rsip_sw_sha256_round_cnt])
Run the 64-round SHA-256 compression loop over one message schedule.
Definition ra8_rsip.c:578
static ra8_rsip_event_fn_t s_rsip_fn
Currently attached interrupt callback, or nullptr.
Definition ra8_rsip.c:107
static ra8_err_t internal_hmac_outer(const uint8_t key_block[k_ra8_rsip_sha256_block], const uint8_t inner[k_ra8_rsip_sha256_digest_bytes], uint8_t *mac_out)
Compute SHA256(K_opad || inner_digest) for HMAC.
Definition ra8_rsip.c:910
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
ra8_err_t ra8_rsip_sha256(const uint8_t *msg, uint32_t msg_len, uint8_t *digest)
Compute SHA-256 of an in-memory buffer.
Definition ra8_rsip.c:397
sha256_lane_t
FIPS 180-4 6.2.2 SHA-256 working-state lane indices a..h.
Definition ra8_rsip.c:546
@ k_sha256_lane_h
Sha256 lane h.
Definition ra8_rsip.c:554
@ k_sha256_lane_f
Sha256 lane f.
Definition ra8_rsip.c:552
@ k_sha256_lane_d
Sha256 lane d.
Definition ra8_rsip.c:550
@ k_sha256_lane_c
Sha256 lane c.
Definition ra8_rsip.c:549
@ k_sha256_lane_e
Sha256 lane e.
Definition ra8_rsip.c:551
@ k_sha256_lane_g
Sha256 lane g.
Definition ra8_rsip.c:553
@ k_sha256_lane_a
Sha256 lane a.
Definition ra8_rsip.c:547
@ k_sha256_lane_b
Sha256 lane b.
Definition ra8_rsip.c:548
static const uint32_t s_sw_sha256_h0[k_ra8_rsip_sw_sha256_state_w]
FIPS PUB 180-4 Section 5.3.3 initial hash value H(0).
Definition ra8_rsip.c:514
static void internal_sw_sha256_schedule(uint32_t w[k_ra8_rsip_sw_sha256_round_cnt], const uint8_t block[k_ra8_rsip_sha256_block])
Definition ra8_rsip.c:522
ra8_err_t ra8_rsip_sha256_init(ra8_rsip_sha256_ctx_t *ctx)
Initialise a streaming SHA-256 context.
Definition ra8_rsip.c:747
ra8_err_t ra8_rsip_attach_handler(ra8_rsip_event_fn_t fn, void *ctx)
Attach a single shared interrupt callback.
Definition ra8_rsip.c:307
static ra8_err_t internal_run_bist(void)
Arm the BIST and wait for STATUS.BIST_OK.
Definition ra8_rsip.c:166
Renesas Secure IP (RSIP-E50D) HAL driver – public API.
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.
@ k_ra8_rsip_sha256_state_words
SHA-256 chaining-state words.
@ k_ra8_rsip_sha256_block
SHA-256 message-block byte length.
@ k_ra8_rsip_hmac_inner_pad
RFC 2104 inner-pad fill byte.
@ k_ra8_rsip_hmac_outer_pad
RFC 2104 outer-pad fill byte.
void(* ra8_rsip_event_fn_t)(void *ctx, uint32_t isr)
RSIP interrupt callback.
Cross-TU surface for the ra8_rsip driver split.
@ k_ra8_rsip_byte_bits
Shift one byte.
@ k_ra8_rsip_word_shift
log2(sizeof(uint32_t)).
@ k_ra8_rsip_byte_shift_3
Shift to top byte of word.
@ k_ra8_rsip_byte_mask
Mask one byte out of a word.
@ k_ra8_rsip_poll_budget
Max iterations for any spin loop.
@ k_ra8_rsip_byte_shift_2
Shift to high half of low word.
Renesas Secure IP (RSIP-E50D) register layout for the RA8D2.
@ k_ra8_rsip_hash_sha256
SHA-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_trng_word_bytes
Bytes per TRNG read.
@ k_ra8_rsip_sha256_digest_words
SHA-256 = 8 * uint32_t.
@ k_ra8_rsip_sha256_digest_bytes
SHA-256 digest length.
@ k_ra8_rsip_mask_isr_done
ISR.DONE bit.
@ k_ra8_rsip_mask_isr_all
Union of ISR bits.
@ k_ra8_rsip_mask_status_bistok
STATUS.BIST_OK.
@ k_ra8_rsip_mask_ctrl_bist
CTRL.BIST bit.
@ k_ra8_rsip_mask_ctrl_reset
CTRL.RESET bit.
@ k_ra8_rsip_mask_status_ready
STATUS.READY bit.
@ k_ra8_rsip_mask_ctrl_enable
CTRL.ENABLE bit.
ra8_rsip_off_t
Byte offsets of every register the HAL touches.
@ k_ra8_rsip_off_ctrl
Engine control word.
@ k_ra8_rsip_off_status
Status / state monitor.
@ k_ra8_rsip_off_hash_digest
HASH output digest base.
@ k_ra8_rsip_off_isr
Interrupt status (W1C).
@ k_ra8_rsip_off_rnd_ctrl
TRNG control word.
@ k_ra8_rsip_off_rnd_data
TRNG output (32-bit per read).
@ k_ra8_rsip_off_hash_status
HASH ready / done flags.
@ k_ra8_rsip_off_rnd_status
TRNG ready / health flags.
@ k_ra8_rsip_off_hash_ctrl
HASH control (algorithm select).
@ k_ra8_rsip_off_hash_data_in
HASH input window (32-bit each).
Initial configuration for ra8_rsip_init.
bool run_bist
true -> arm BIST after MSTP release.
Streaming state for incremental HMAC-SHA-256.
ra8_rsip_sha256_ctx_t inner
Running inner-hash state.
uint8_t key_block[k_ra8_rsip_sha256_block]
Prepared 64-byte key block.
uint8_t initialized
1 = ready, 0 = unset.
Streaming state for incremental SHA-256.
uint32_t state[k_ra8_rsip_sha256_state_words]
Chaining words H0..H7.
uint8_t block[k_ra8_rsip_sha256_block]
Partial message block.
uint32_t used
Bytes in block.
uint8_t initialized
1 = ready, 0 = unset.
uint64_t total_bytes
Bytes absorbed so far.