ra8-firmware 0.1.0
Bare-metal firmware for the Renesas RA8 family (RA8D2 / RA8P1)
Loading...
Searching...
No Matches
ra8_rsip_cipher.c
Go to the documentation of this file.
1
39
40#include <stdint.h>
41
42#include "ra8_attributes.h"
43#include "ra8_check.h"
44#include "ra8_err.h"
45#include "ra8_log.h"
46#include "ra8_rsip.h"
47#include "ra8_rsip_internal.h"
48#include "ra8_rsip_regs.h"
49
61static const char* s_tag = "RSIP";
62
63/* ===========================================================================
64 * Round-3 byte-packing primitives + mailbox completion
65 * ===========================================================================
66 */
67
68uint32_t priv_pack_le(const uint8_t* p)
69{
70 return ((uint32_t)p[0]) | (((uint32_t)p[1]) << k_ra8_rsip_byte_bits) |
71 (((uint32_t)p[2]) << k_ra8_rsip_byte_shift_2) |
72 (((uint32_t)p[3]) << k_ra8_rsip_byte_shift_3);
73}
74
75void priv_unpack_le(uint32_t word, uint8_t* p)
76{
77 p[0] = (uint8_t)(word & k_ra8_rsip_byte_mask);
78 p[1] = (uint8_t)((word >> k_ra8_rsip_byte_bits) & k_ra8_rsip_byte_mask);
79 p[2] = (uint8_t)((word >> k_ra8_rsip_byte_shift_2) & k_ra8_rsip_byte_mask);
80 p[3] = (uint8_t)((word >> k_ra8_rsip_byte_shift_3) & k_ra8_rsip_byte_mask);
81}
82
84{
85 /* HUM Ch 52.1 "Application Key Management" p 3303 */
86 /* Handle-body sizes mirror FSP r_rsip_key_injection.c. */
87 switch (cmd) {
89 return (uint32_t)k_ra8_rsip_handle_words_aes128;
91 return (uint32_t)k_ra8_rsip_handle_words_aes192;
93 return (uint32_t)k_ra8_rsip_handle_words_aes256;
95 return (uint32_t)k_ra8_rsip_handle_words_chacha20;
126 default:
127 return 0U;
128 }
129}
130
131ra8_err_t priv_complete(uint32_t done_mask)
132{
133 /* HUM Ch 52.1 "Overview" p 3302 */
134 const ra8_err_t wait_err = priv_wait_bit(k_ra8_rsip_off_isr, done_mask);
135 if (wait_err != k_ra8_ok) {
136 return wait_err;
137 }
138 /* HUM Ch 52.1 "Overview" p 3302 */
139 /* Read MBOX_RET; non-zero indicates engine-side error. */
140 const uint32_t ret = *ra8_rsip_reg32(k_ra8_rsip_off_mbox_ret);
141 /* W1C ack on the completion bit. */
143 if (ret != 0U) {
144 return k_ra8_err_hw_error;
145 }
146 return k_ra8_ok;
147}
148
150void priv_push_bytes_to_port(ra8_rsip_off_t off, const uint8_t* in, uint32_t len)
151{
152 volatile uint32_t* port = ra8_rsip_reg32(off);
153 uint32_t i = 0U;
154 while ((i + (uint32_t)k_ra8_rsip_trng_word_bytes) <= len) {
155 *port = priv_pack_le(&in[i]);
156 i += (uint32_t)k_ra8_rsip_trng_word_bytes;
157 }
158 if (i < len) {
159 uint32_t tail = 0U;
160 for (uint32_t b = 0U; (i + b) < len; ++b) {
161 tail |= ((uint32_t)in[i + b]) << (b * k_ra8_rsip_byte_bits);
162 }
163 *port = tail;
164 }
165}
166
168void priv_push_iv_lanes(ra8_rsip_off_t base, const uint8_t* iv, uint32_t iv_len)
169{
170 for (uint32_t w = 0U; w < k_ra8_rsip_iv_words; ++w) {
171 const uint32_t lane_base = w * (uint32_t)k_ra8_rsip_trng_word_bytes;
172 uint32_t lane = 0U;
173 for (uint32_t b = 0U; b < (uint32_t)k_ra8_rsip_trng_word_bytes; ++b) {
174 const uint32_t index = lane_base + b;
175 if (index < iv_len) {
176 lane |= (uint32_t)iv[index] << (b * k_ra8_rsip_byte_bits);
177 }
178 }
179 /* Computed lane offset is a HUM-defined register, not an enumerator. */
180 const ra8_rsip_off_t off =
181 (ra8_rsip_off_t)((uint32_t)base + (uint16_t)(w << k_ra8_rsip_word_shift));
182 *ra8_rsip_reg32(off) = lane;
183 }
184}
185
188{
189 for (uint32_t w = 0U; w < handle->body_words; ++w) {
191 }
192}
193
195{
196 if (handle == nullptr) {
197 return;
198 }
199 /* HUM Ch 52.1 "Application Key Management" p 3303 */
201 priv_push_handle_body(handle);
202}
203
204uint8_t priv_aes_alg_byte(uint32_t alg)
205{
206 switch (alg) {
213 default:
214 return 0U;
215 }
216}
217
218/*
219 * The RSIP-E50D symmetric-cipher + wrapped-key-install family (AES ECB / CBC /
220 * CTR / GCM / CCM, ChaCha20 + Poly1305, and the plaintext / OEM key-install
221 * flows) is NOT backed by a documented register interface on this silicon. HUM
222 * Ch 52 "Renesas Secure IP (RSIP-E50D)" is a six-page feature overview
223 * (p 3302-3307) with no command-register map; the vendor engine is driven
224 * through an encrypted firmware mailbox, not the MMIO opcodes modelled below.
225 * The command-path bodies here only round-trip the host register fake;
226 * they do NOT compute a real cipher / AEAD / MAC result. They compile only
227 * under the insecure-stub / off-target guard so a production image gets the
228 * fail-closed #else and can never mistake these bytes for real ciphertext or a
229 * valid tag. The shipping symmetric crypto is tf-psa-crypto on the M85,
230 * silicon-proven in psa_crypto_hil; NetX Crypto is linked with its own built-in
231 * software AES / SHA-256 (there is no RSIP ALT shim), so no NetX consumer
232 * depends on this fail-closed path (issue #214). The register pokes below
233 * therefore carry NO HUM citation: there is no real register map to cite.
234 */
235#if defined(RA8_INSECURE_STUB_CRYPTO) || defined(RA8_OFF_TARGET)
236
237/* Stream ``len`` bytes into the data input window -- see surrounding code and HUM citations. */
239static void internal_push_data(const uint8_t* in, uint32_t len)
240{
241 /* Stream 32-bit words through DATA_IN0..3 round-robin. */
242 uint32_t i = 0U;
243 uint8_t lane = 0U;
244 while ((i + (uint32_t)k_ra8_rsip_trng_word_bytes) <= len) {
245 const uint32_t word = priv_pack_le(&in[i]);
246 const ra8_rsip_off_t off =
248 (uint16_t)((uint32_t)lane << k_ra8_rsip_word_shift));
249 *ra8_rsip_reg32(off) = word;
250 i += (uint32_t)k_ra8_rsip_trng_word_bytes;
251 lane = (uint8_t)((lane + 1U) & (k_ra8_rsip_aes_block_w - 1U));
252 }
253 if (i < len) {
254 uint32_t tail = 0U;
255 for (uint32_t b = 0U; (i + b) < len; ++b) {
256 tail |= ((uint32_t)in[i + b]) << (b * k_ra8_rsip_byte_bits);
257 }
258 const ra8_rsip_off_t off =
260 (uint16_t)((uint32_t)lane << k_ra8_rsip_word_shift));
261 *ra8_rsip_reg32(off) = tail;
262 }
263}
264
265/* Pull ``len`` bytes back from the data output window -- see surrounding code and HUM citations. */
267static void internal_pull_data(uint8_t* out, uint32_t len)
268{
269 uint32_t i = 0U;
270 uint8_t lane = 0U;
271 while ((i + (uint32_t)k_ra8_rsip_trng_word_bytes) <= len) {
272 const ra8_rsip_off_t off =
274 (uint16_t)((uint32_t)lane << k_ra8_rsip_word_shift));
275 const uint32_t word = *ra8_rsip_reg32(off);
276 priv_unpack_le(word, &out[i]);
277 i += (uint32_t)k_ra8_rsip_trng_word_bytes;
278 lane = (uint8_t)((lane + 1U) & (k_ra8_rsip_aes_block_w - 1U));
279 }
280 if (i < len) {
281 const ra8_rsip_off_t off =
283 (uint16_t)((uint32_t)lane << k_ra8_rsip_word_shift));
284 const uint32_t word = *ra8_rsip_reg32(off);
285 for (uint32_t b = 0U; (i + b) < len; ++b) {
286 out[i + b] = (uint8_t)((word >> (b * k_ra8_rsip_byte_bits)) & k_ra8_rsip_byte_mask);
287 }
288 }
289}
290
291/* Push a bounded IV / nonce into the SYM_IV0 lanes -- see surrounding code and HUM citations. */
293static void internal_push_iv(const uint8_t* iv, uint32_t iv_len)
294{
295 if (iv == nullptr) {
296 return;
297 }
299}
300
301/* Issue an OEM key-install opcode and read the wrapped body back -- see surrounding code and HUM citations. */
303static ra8_err_t internal_oem_install(ra8_rsip_oem_cmd_t cmd,
304 const uint8_t* iv,
305 const uint8_t* src,
306 uint32_t src_len,
308{
309 const uint32_t words = priv_handle_words_for(cmd);
310 if (words == 0U) {
312 }
313
314 /* Set the OEM opcode + push the IV + plaintext body. */
315 *ra8_rsip_reg32(k_ra8_rsip_off_oem_ctrl) = (uint32_t)cmd;
317
318 if (iv != nullptr) {
319 for (uint32_t w = 0U; w < k_ra8_rsip_iv_words; ++w) {
321 priv_pack_le(&iv[(size_t)w * (size_t)k_ra8_rsip_trng_word_bytes]);
322 }
323 }
324 if (src != nullptr) {
325 internal_push_data(src, src_len);
326 }
327
328 /* Fire the install command via MBOX. */
329 *ra8_rsip_reg32(k_ra8_rsip_off_mbox_op) = (uint32_t)cmd;
330
332 if (err != k_ra8_ok) {
333 return err;
334 }
335
336 out->alg = (uint32_t)cmd;
337 out->body_words = words;
338 /* Pull body words back from the staging port. */
339 for (uint32_t w = 0U; w < words; ++w) {
341 }
342 /* Zero the remainder so unused bytes don't leak old data. */
343 for (uint32_t w = words; w < (uint32_t)k_ra8_rsip_handle_words_rsa4096_priv; ++w) {
344 out->body[w] = 0U;
345 }
346 return k_ra8_ok;
347}
348
349/* ===========================================================================
350 * Round-3 entry points: key install
351 * ===========================================================================
352 */
353
355{
356 RA8_CHECK_NULL_PTR(key, s_tag, "key must not be nullptr");
357 RA8_CHECK_NULL_PTR(out, s_tag, "out must not be nullptr");
358 return internal_oem_install(k_ra8_rsip_oem_cmd_aes128,
359 nullptr,
360 key,
362 out);
363}
364
366{
367 RA8_CHECK_NULL_PTR(key, s_tag, "key must not be nullptr");
368 RA8_CHECK_NULL_PTR(out, s_tag, "out must not be nullptr");
369 return internal_oem_install(k_ra8_rsip_oem_cmd_aes192,
370 nullptr,
371 key,
373 out);
374}
375
377{
378 RA8_CHECK_NULL_PTR(key, s_tag, "key must not be nullptr");
379 RA8_CHECK_NULL_PTR(out, s_tag, "out must not be nullptr");
380 return internal_oem_install(k_ra8_rsip_oem_cmd_aes256,
381 nullptr,
382 key,
384 out);
385}
386
388{
389 RA8_CHECK_NULL_PTR(key, s_tag, "key must not be nullptr");
390 RA8_CHECK_NULL_PTR(out, s_tag, "out must not be nullptr");
391 return internal_oem_install(k_ra8_rsip_oem_cmd_chacha20,
392 nullptr,
393 key,
395 out);
396}
397
399 const uint8_t* key,
400 uint32_t key_len,
402{
403 RA8_CHECK_NULL_PTR(key, s_tag, "key must not be nullptr");
404 RA8_CHECK_NULL_PTR(out, s_tag, "out must not be nullptr");
405 if (key_len == 0U) {
407 }
408 switch (alg) {
415 break;
416 default:
418 }
419 return internal_oem_install(alg, nullptr, key, key_len, out);
420}
421
423 const uint8_t* iv,
424 const uint8_t* oem_blob,
425 uint32_t blob_len,
427{
428 RA8_CHECK_NULL_PTR(iv, s_tag, "iv must not be nullptr");
429 RA8_CHECK_NULL_PTR(oem_blob, s_tag, "oem_blob must not be nullptr");
430 RA8_CHECK_NULL_PTR(out, s_tag, "out must not be nullptr");
431 if (cmd == k_ra8_rsip_oem_cmd_invalid) {
433 }
434 if (blob_len == 0U) {
436 }
437 return internal_oem_install(cmd, iv, oem_blob, blob_len, out);
438}
439
440/* ===========================================================================
441 * Round-3 entry points: AES symmetric cipher
442 * ===========================================================================
443 */
444
445/* Drive one block / multi-block cipher transaction -- see surrounding code and HUM citations. */
447static ra8_err_t internal_sym_run(const ra8_rsip_key_handle_t* key,
448 uint8_t alg_byte,
451 const uint8_t* iv,
452 const uint8_t* in,
453 uint8_t* out,
454 uint32_t len)
455{
456 priv_load_handle(key);
457 internal_push_iv(iv, (uint32_t)k_ra8_rsip_iv_words * (uint32_t)k_ra8_rsip_trng_word_bytes);
458
459 /* SYM_CTRL = (dir << 16) | (mode << 8) | alg_byte. */
460 const uint32_t cmd = ((uint32_t)dir << k_ra8_rsip_byte_shift_2) |
461 ((uint32_t)mode << k_ra8_rsip_byte_bits) | (uint32_t)alg_byte;
463
464 internal_push_data(in, len);
466
468 if (err != k_ra8_ok) {
469 return err;
470 }
471 internal_pull_data(out, len);
472 return k_ra8_ok;
473}
474
478 const uint8_t* iv,
479 const uint8_t* in,
480 uint8_t* out,
481 uint32_t len)
482{
483 RA8_CHECK_NULL_PTR(key, s_tag, "key must not be nullptr");
484 RA8_CHECK_NULL_PTR(in, s_tag, "in must not be nullptr");
485 RA8_CHECK_NULL_PTR(out, s_tag, "out must not be nullptr");
486 if ((mode == k_ra8_rsip_aes_mode_gcm) || (mode == k_ra8_rsip_aes_mode_ccm)) {
487 return k_ra8_err_invalid_arg; /* AEAD has dedicated entry points. */
488 }
489 if (((mode == k_ra8_rsip_aes_mode_ecb) || (mode == k_ra8_rsip_aes_mode_cbc) ||
490 (mode == k_ra8_rsip_aes_mode_cmac)) &&
491 ((len & ((uint32_t)k_ra8_rsip_aes_block_bytes - 1U)) != 0U)) {
493 }
494 const uint8_t alg_byte = priv_aes_alg_byte(key->alg);
495 if (alg_byte == 0U) {
497 }
498 return internal_sym_run(key, alg_byte, mode, dir, iv, in, out, len);
499}
500
501/* Push 16 tag bytes through the SYM_TAG port (decrypt path) -- see surrounding code and HUM citations. */
503static void internal_aead_push_tag(const uint8_t* tag)
504{
505 for (uint32_t w = 0U; w < k_ra8_rsip_aes_block_w; ++w) {
507 priv_pack_le(&tag[(size_t)w * (size_t)k_ra8_rsip_trng_word_bytes]);
508 }
509}
510
511/* Pull 16 tag bytes from the SYM_TAG port (encrypt path) -- see surrounding code and HUM citations. */
513static void internal_aead_pull_tag(uint8_t* tag)
514{
515 for (uint32_t w = 0U; w < k_ra8_rsip_aes_block_w; ++w) {
516 const uint32_t word = *ra8_rsip_reg32(k_ra8_rsip_off_sym_tag);
517 priv_unpack_le(word, &tag[(size_t)w * (size_t)k_ra8_rsip_trng_word_bytes]);
518 }
519}
520
521/* internal aead run -- see surrounding code and HUM citations. */
523static ra8_err_t internal_aead_run(const ra8_rsip_key_handle_t* key,
524 uint8_t alg_byte,
527 const uint8_t* iv,
528 const uint8_t* aad,
529 uint32_t aad_len,
530 const uint8_t* in,
531 uint8_t* out,
532 uint32_t in_len,
533 uint8_t* tag)
534{
535 priv_load_handle(key);
536 internal_push_iv(iv, (uint32_t)k_ra8_rsip_aead_iv_bytes);
537 /* AAD + body length descriptors. */
540
541 if ((aad != nullptr) && (aad_len > 0U)) {
542 /* Push AAD bytes one word at a time through the AAD lane. */
544 }
545
546 /* On decrypt, push the supplied tag in for verification. */
547 if (dir == k_ra8_rsip_dir_decrypt) {
548 internal_aead_push_tag(tag);
549 }
550
551 const uint32_t cmd = ((uint32_t)dir << k_ra8_rsip_byte_shift_2) |
552 ((uint32_t)mode << k_ra8_rsip_byte_bits) | (uint32_t)alg_byte;
554 internal_push_data(in, in_len);
556
558 if (err != k_ra8_ok) {
559 return err;
560 }
561 internal_pull_data(out, in_len);
562 /* On encrypt, read the engine-computed tag back. */
563 if (dir == k_ra8_rsip_dir_encrypt) {
564 internal_aead_pull_tag(tag);
565 }
566 return k_ra8_ok;
567}
568
571 const uint8_t* iv,
572 const uint8_t* aad,
573 uint32_t aad_len,
574 const uint8_t* in,
575 uint8_t* out,
576 uint32_t in_len,
577 uint8_t* tag)
578{
579 RA8_CHECK_NULL_PTR(key, s_tag, "key must not be nullptr");
580 RA8_CHECK_NULL_PTR(iv, s_tag, "iv must not be nullptr");
581 RA8_CHECK_NULL_PTR(in, s_tag, "in must not be nullptr");
582 RA8_CHECK_NULL_PTR(out, s_tag, "out must not be nullptr");
583 RA8_CHECK_NULL_PTR(tag, s_tag, "tag must not be nullptr");
584 const uint8_t alg_byte = priv_aes_alg_byte(key->alg);
585 if (alg_byte == 0U) {
587 }
588 return internal_aead_run(key,
589 alg_byte,
591 dir,
592 iv,
593 aad,
594 aad_len,
595 in,
596 out,
597 in_len,
598 tag);
599}
600
603 const uint8_t* iv,
604 const uint8_t* aad,
605 uint32_t aad_len,
606 const uint8_t* in,
607 uint8_t* out,
608 uint32_t in_len,
609 uint8_t* tag)
610{
611 RA8_CHECK_NULL_PTR(key, s_tag, "key must not be nullptr");
612 RA8_CHECK_NULL_PTR(iv, s_tag, "iv must not be nullptr");
613 RA8_CHECK_NULL_PTR(in, s_tag, "in must not be nullptr");
614 RA8_CHECK_NULL_PTR(out, s_tag, "out must not be nullptr");
615 RA8_CHECK_NULL_PTR(tag, s_tag, "tag must not be nullptr");
616 const uint8_t alg_byte = priv_aes_alg_byte(key->alg);
617 if (alg_byte == 0U) {
619 }
620 return internal_aead_run(key,
621 alg_byte,
623 dir,
624 iv,
625 aad,
626 aad_len,
627 in,
628 out,
629 in_len,
630 tag);
631}
632
633/* ===========================================================================
634 * Round-3 entry points: ChaCha20 + Poly1305
635 * ===========================================================================
636 */
637
638/* Stage the ChaCha20-style 16-byte IV (counter || 12-byte nonce) -- see surrounding code and HUM citations. */
640static void internal_chacha20_push_iv(uint32_t counter, const uint8_t* nonce)
641{
642 /* ChaCha20 IV layout: counter || 12-byte nonce. */
646 priv_pack_le(&nonce[(uint32_t)k_ra8_rsip_trng_word_bytes]);
648 priv_pack_le(&nonce[(size_t)2U * (size_t)k_ra8_rsip_trng_word_bytes]);
649}
650
653 const uint8_t* nonce,
654 uint32_t counter,
655 const uint8_t* in,
656 uint8_t* out,
657 uint32_t len)
658{
659 RA8_CHECK_NULL_PTR(key, s_tag, "key must not be nullptr");
660 RA8_CHECK_NULL_PTR(nonce, s_tag, "nonce must not be nullptr");
661 RA8_CHECK_NULL_PTR(in, s_tag, "in must not be nullptr");
662 RA8_CHECK_NULL_PTR(out, s_tag, "out must not be nullptr");
663 if (key->alg != k_ra8_rsip_oem_cmd_chacha20) {
665 }
666 priv_load_handle(key);
667 internal_chacha20_push_iv(counter, nonce);
668
669 const uint32_t cmd = ((uint32_t)dir << k_ra8_rsip_byte_shift_2) |
673 internal_push_data(in, len);
675
677 if (err != k_ra8_ok) {
678 return err;
679 }
680 internal_pull_data(out, len);
681 return k_ra8_ok;
682}
683
686 const uint8_t* nonce,
687 const uint8_t* aad,
688 uint32_t aad_len,
689 const uint8_t* in,
690 uint8_t* out,
691 uint32_t in_len,
692 uint8_t* tag)
693{
694 RA8_CHECK_NULL_PTR(key, s_tag, "key must not be nullptr");
695 RA8_CHECK_NULL_PTR(nonce, s_tag, "nonce must not be nullptr");
696 RA8_CHECK_NULL_PTR(in, s_tag, "in must not be nullptr");
697 RA8_CHECK_NULL_PTR(out, s_tag, "out must not be nullptr");
698 RA8_CHECK_NULL_PTR(tag, s_tag, "tag must not be nullptr");
699 if (key->alg != k_ra8_rsip_oem_cmd_chacha20) {
701 }
702 return internal_aead_run(key,
705 dir,
706 nonce,
707 aad,
708 aad_len,
709 in,
710 out,
711 in_len,
712 tag);
713}
714
716ra8_rsip_poly1305(const uint8_t* one_time_key, const uint8_t* msg, uint32_t msg_len, uint8_t* tag)
717{
718 RA8_CHECK_NULL_PTR(one_time_key, s_tag, "one_time_key must not be nullptr");
719 RA8_CHECK_NULL_PTR(tag, s_tag, "tag must not be nullptr");
720 if ((msg == nullptr) && (msg_len != 0U)) {
721 return k_ra8_err_null_ptr;
722 }
723
724 /* Stage one-time key as a ChaCha20 key. */
725 for (uint32_t w = 0U; w < (uint32_t)k_ra8_rsip_handle_words_chacha20; ++w) {
726 if (w < ((uint32_t)k_ra8_rsip_chacha_key_bytes / (uint32_t)k_ra8_rsip_trng_word_bytes)) {
728 priv_pack_le(&one_time_key[(size_t)w * (size_t)k_ra8_rsip_trng_word_bytes]);
729 } else {
731 }
732 }
734 if (msg_len > 0U) {
735 internal_push_data(msg, msg_len);
736 }
738
740 if (err != k_ra8_ok) {
741 return err;
742 }
743 for (uint32_t w = 0U; w < k_ra8_rsip_aes_block_w; ++w) {
744 const uint32_t word = *ra8_rsip_reg32(k_ra8_rsip_off_sym_tag);
745 priv_unpack_le(word, &tag[(size_t)w * (size_t)k_ra8_rsip_trng_word_bytes]);
746 }
747 return k_ra8_ok;
748}
749
750#else /* production build: neither RA8_INSECURE_STUB_CRYPTO nor RA8_OFF_TARGET */
751
752/*
753 * Fail-closed production variant. With no real RSIP symmetric-cipher /
754 * key-install backend on this silicon, every entry point returns a hard error
755 * (never k_ra8_ok) so a production image cannot mistake the fake
756 * command-path for real ciphertext, a valid tag, or an installed key handle.
757 * No production caller depends on a real result here: NetX Crypto uses its own
758 * built-in software AES / SHA-256, and general callers use tf-psa-crypto on the
759 * M85.
760 */
761
763{
764 RA8_CHECK_NULL_PTR(key, s_tag, "aes128_install_plain: key must not be nullptr");
765 RA8_CHECK_NULL_PTR(out, s_tag, "aes128_install_plain: out must not be nullptr");
767}
768
770{
771 RA8_CHECK_NULL_PTR(key, s_tag, "aes192_install_plain: key must not be nullptr");
772 RA8_CHECK_NULL_PTR(out, s_tag, "aes192_install_plain: out must not be nullptr");
774}
775
777{
778 RA8_CHECK_NULL_PTR(key, s_tag, "aes256_install_plain: key must not be nullptr");
779 RA8_CHECK_NULL_PTR(out, s_tag, "aes256_install_plain: out must not be nullptr");
781}
782
784{
785 RA8_CHECK_NULL_PTR(key, s_tag, "chacha20_install_plain: key must not be nullptr");
786 RA8_CHECK_NULL_PTR(out, s_tag, "chacha20_install_plain: out must not be nullptr");
788}
789
791 const uint8_t* key,
792 uint32_t key_len,
794{
795 RA8_CHECK_NULL_PTR(key, s_tag, "hmac_install_plain: key must not be nullptr");
796 RA8_CHECK_NULL_PTR(out, s_tag, "hmac_install_plain: out must not be nullptr");
797 (void)alg;
798 (void)key_len;
800}
801
803 const uint8_t* iv,
804 const uint8_t* oem_blob,
805 uint32_t blob_len,
807{
808 RA8_CHECK_NULL_PTR(oem_blob, s_tag, "oem_install: oem_blob must not be nullptr");
809 RA8_CHECK_NULL_PTR(out, s_tag, "oem_install: out must not be nullptr");
810 (void)cmd;
811 (void)iv;
812 (void)blob_len;
814}
815
819 const uint8_t* iv,
820 const uint8_t* in,
821 uint8_t* out,
822 uint32_t len)
823{
824 RA8_CHECK_NULL_PTR(key, s_tag, "aes_cipher: key must not be nullptr");
825 RA8_CHECK_NULL_PTR(out, s_tag, "aes_cipher: out must not be nullptr");
826 (void)mode;
827 (void)dir;
828 (void)iv;
829 (void)in;
830 (void)len;
832}
833
836 const uint8_t* iv,
837 const uint8_t* aad,
838 uint32_t aad_len,
839 const uint8_t* in,
840 uint8_t* out,
841 uint32_t in_len,
842 uint8_t* tag)
843{
844 RA8_CHECK_NULL_PTR(key, s_tag, "aes_gcm: key must not be nullptr");
845 RA8_CHECK_NULL_PTR(tag, s_tag, "aes_gcm: tag must not be nullptr");
846 (void)dir;
847 (void)iv;
848 (void)aad;
849 (void)aad_len;
850 (void)in;
851 (void)out;
852 (void)in_len;
854}
855
858 const uint8_t* iv,
859 const uint8_t* aad,
860 uint32_t aad_len,
861 const uint8_t* in,
862 uint8_t* out,
863 uint32_t in_len,
864 uint8_t* tag)
865{
866 RA8_CHECK_NULL_PTR(key, s_tag, "aes_ccm: key must not be nullptr");
867 RA8_CHECK_NULL_PTR(tag, s_tag, "aes_ccm: tag must not be nullptr");
868 (void)dir;
869 (void)iv;
870 (void)aad;
871 (void)aad_len;
872 (void)in;
873 (void)out;
874 (void)in_len;
876}
877
880 const uint8_t* nonce,
881 uint32_t counter,
882 const uint8_t* in,
883 uint8_t* out,
884 uint32_t len)
885{
886 RA8_CHECK_NULL_PTR(key, s_tag, "chacha20: key must not be nullptr");
887 RA8_CHECK_NULL_PTR(out, s_tag, "chacha20: out must not be nullptr");
888 (void)dir;
889 (void)nonce;
890 (void)counter;
891 (void)in;
892 (void)len;
894}
895
898 const uint8_t* nonce,
899 const uint8_t* aad,
900 uint32_t aad_len,
901 const uint8_t* in,
902 uint8_t* out,
903 uint32_t in_len,
904 uint8_t* tag)
905{
906 RA8_CHECK_NULL_PTR(key, s_tag, "chacha20_poly1305: key must not be nullptr");
907 RA8_CHECK_NULL_PTR(tag, s_tag, "chacha20_poly1305: tag must not be nullptr");
908 (void)dir;
909 (void)nonce;
910 (void)aad;
911 (void)aad_len;
912 (void)in;
913 (void)out;
914 (void)in_len;
916}
917
919ra8_rsip_poly1305(const uint8_t* one_time_key, const uint8_t* msg, uint32_t msg_len, uint8_t* tag)
920{
921 RA8_CHECK_NULL_PTR(one_time_key, s_tag, "poly1305: one_time_key must not be nullptr");
922 RA8_CHECK_NULL_PTR(tag, s_tag, "poly1305: tag must not be nullptr");
923 (void)msg;
924 (void)msg_len;
926}
927
928#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_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_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_wait_bit(ra8_rsip_off_t offset, uint32_t mask)
Implementation of priv_wait_bit() – bounded MMIO mask spin.
Definition ra8_rsip.c:120
Renesas Secure IP (RSIP-E50D) HAL driver – public API.
ra8_err_t ra8_rsip_oem_install(ra8_rsip_oem_cmd_t cmd, const uint8_t *iv, const uint8_t *oem_blob, uint32_t blob_len, ra8_rsip_key_handle_t *out)
Install an OEM-encrypted key blob into the wrapped vault.
ra8_err_t ra8_rsip_chacha20_poly1305(const ra8_rsip_key_handle_t *key, ra8_rsip_aes_dir_t dir, const uint8_t *nonce, const uint8_t *aad, uint32_t aad_len, const uint8_t *in, uint8_t *out, uint32_t in_len, uint8_t *tag)
ChaCha20-Poly1305 AEAD encrypt or decrypt (RFC 7539).
ra8_err_t ra8_rsip_aes256_install_plain(const uint8_t *key, ra8_rsip_key_handle_t *out)
Wrap a 32-byte AES-256 key (see ra8_rsip_aes128_install_plain).
ra8_err_t ra8_rsip_aes_cipher(const ra8_rsip_key_handle_t *key, ra8_rsip_aes_mode_t mode, ra8_rsip_aes_dir_t dir, const uint8_t *iv, const uint8_t *in, uint8_t *out, uint32_t len)
Encrypt or decrypt a buffer with AES in a non-AEAD mode.
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.
ra8_err_t ra8_rsip_poly1305(const uint8_t *one_time_key, const uint8_t *msg, uint32_t msg_len, uint8_t *tag)
Poly1305 MAC over a buffer using a 32-byte one-time key.
ra8_err_t ra8_rsip_hmac_install_plain(ra8_rsip_oem_cmd_t alg, const uint8_t *key, uint32_t key_len, ra8_rsip_key_handle_t *out)
Wrap an HMAC key for use by the HMAC engine.
ra8_err_t ra8_rsip_chacha20(const ra8_rsip_key_handle_t *key, ra8_rsip_aes_dir_t dir, const uint8_t *nonce, uint32_t counter, const uint8_t *in, uint8_t *out, uint32_t len)
ChaCha20 stream encrypt or decrypt (RFC 7539, no AEAD).
ra8_err_t ra8_rsip_aes128_install_plain(const uint8_t *key, ra8_rsip_key_handle_t *out)
Wrap a 16-byte AES-128 key for use by the engine.
uint32_t priv_handle_words_for(ra8_rsip_oem_cmd_t cmd)
Map an OEM opcode to the wrapped-key body word count.
ra8_err_t ra8_rsip_chacha20_install_plain(const uint8_t *key, ra8_rsip_key_handle_t *out)
Wrap a 32-byte ChaCha20 key.
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 ra8_rsip_aes_gcm(const ra8_rsip_key_handle_t *key, ra8_rsip_aes_dir_t dir, const uint8_t *iv, const uint8_t *aad, uint32_t aad_len, const uint8_t *in, uint8_t *out, uint32_t in_len, uint8_t *tag)
AES-GCM encrypt or decrypt with associated data.
ra8_err_t ra8_rsip_aes192_install_plain(const uint8_t *key, ra8_rsip_key_handle_t *out)
Wrap a 24-byte AES-192 key (see ra8_rsip_aes128_install_plain).
ra8_err_t priv_complete(uint32_t done_mask)
Drive a single mailbox completion (DONE poll + ack).
ra8_err_t ra8_rsip_aes_ccm(const ra8_rsip_key_handle_t *key, ra8_rsip_aes_dir_t dir, const uint8_t *iv, const uint8_t *aad, uint32_t aad_len, const uint8_t *in, uint8_t *out, uint32_t in_len, uint8_t *tag)
AES-CCM encrypt or decrypt with associated data.
Cross-TU surface for the ra8_rsip driver split.
@ k_ra8_rsip_iv_words
IV / nonce register lanes.
@ k_ra8_rsip_aes_block_w
16-byte block = 4 * uint32_t.
@ k_ra8_rsip_aead_iv_bytes
Fixed GCM / CCM nonce length.
@ 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_byte_shift_2
Shift to high half of low word.
Renesas Secure IP (RSIP-E50D) register layout for the RA8D2.
@ k_ra8_rsip_sym_alg_chacha20
ChaCha20 stream cipher.
@ k_ra8_rsip_sym_alg_aes128
AES with a 128-bit key.
@ k_ra8_rsip_sym_alg_aes256
AES with a 256-bit key.
@ k_ra8_rsip_sym_alg_aes192
AES with a 192-bit key.
@ k_ra8_rsip_handle_words_hmac_sha384
HMAC-SHA-384 wrapped key.
@ k_ra8_rsip_handle_words_rsa4096_priv
RSA-4096 wrapped private.
@ k_ra8_rsip_handle_words_ecc521_priv
ECC P-521 wrapped private.
@ k_ra8_rsip_handle_words_hmac_sha224
HMAC-SHA-224 wrapped key.
@ k_ra8_rsip_handle_words_chacha20
ChaCha20 wrapped key body.
@ k_ra8_rsip_handle_words_rsa2048_priv
RSA-2048 wrapped private.
@ k_ra8_rsip_handle_words_rsa3072_priv
RSA-3072 wrapped private.
@ k_ra8_rsip_handle_words_aes128
AES-128 wrapped-key body.
@ k_ra8_rsip_handle_words_aes192
AES-192 wrapped-key body.
@ k_ra8_rsip_handle_words_hmac_sha512
HMAC-SHA-512 wrapped key.
@ k_ra8_rsip_handle_words_ecc384_priv
ECC P-384 wrapped private.
@ k_ra8_rsip_handle_words_aes256
AES-256 wrapped-key body.
@ k_ra8_rsip_handle_words_hmac_sha256
HMAC-SHA-256 wrapped key.
@ k_ra8_rsip_handle_words_ecc256_priv
ECC P-256 wrapped private.
ra8_rsip_aes_dir_t
Direction selector for symmetric ciphers.
@ k_ra8_rsip_dir_decrypt
Ciphertext -> Plaintext.
@ k_ra8_rsip_dir_encrypt
Plaintext -> Ciphertext.
@ k_ra8_rsip_chacha_op_poly1305_mac
Poly1305 MAC only.
@ k_ra8_rsip_chacha_op_encrypt
ChaCha20 stream encrypt.
ra8_rsip_oem_cmd_t
OEM-key install opcode written to OEM_CTRL.
@ k_ra8_rsip_oem_cmd_rsa3072_priv
RSA-3072 private.
@ k_ra8_rsip_oem_cmd_ecc_secp521r1_priv
ECC NIST P-521 private.
@ k_ra8_rsip_oem_cmd_rsa4096_priv
RSA-4096 private.
@ k_ra8_rsip_oem_cmd_ecc_secp256r1_priv
ECC NIST P-256 private.
@ k_ra8_rsip_oem_cmd_ecc_brain512r1_priv
ECC Brainpool P-512.
@ k_ra8_rsip_oem_cmd_ecc_secp256k1_priv
ECC secp256k1 private.
@ k_ra8_rsip_oem_cmd_ecc_secp384r1_priv
ECC NIST P-384 private.
@ k_ra8_rsip_oem_cmd_hmac_sha384
HMAC-SHA-384.
@ k_ra8_rsip_oem_cmd_chacha20
ChaCha20.
@ k_ra8_rsip_oem_cmd_aes256
AES-256.
@ k_ra8_rsip_oem_cmd_ecc_brain256r1_priv
ECC Brainpool P-256.
@ k_ra8_rsip_oem_cmd_aes128_xts
AES-128 XTS.
@ k_ra8_rsip_oem_cmd_hmac_sha512_224
HMAC-SHA-512/224.
@ k_ra8_rsip_oem_cmd_aes256_xts
AES-256 XTS.
@ k_ra8_rsip_oem_cmd_aes192
AES-192.
@ k_ra8_rsip_oem_cmd_hmac_sha224
HMAC-SHA-224.
@ k_ra8_rsip_oem_cmd_ecc_brain384r1_priv
ECC Brainpool P-384.
@ k_ra8_rsip_oem_cmd_rsa2048_priv
RSA-2048 private.
@ k_ra8_rsip_oem_cmd_hmac_sha512
HMAC-SHA-512.
@ k_ra8_rsip_oem_cmd_invalid
Sentinel / unused.
@ k_ra8_rsip_oem_cmd_hmac_sha256
HMAC-SHA-256.
@ k_ra8_rsip_oem_cmd_ecc_ed25519_priv
Ed25519 private.
@ k_ra8_rsip_oem_cmd_aes128
AES-128.
@ 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.
ra8_rsip_aes_mode_t
Block-cipher mode selector for the AES engine.
@ k_ra8_rsip_aes_mode_ecb
ECB.
@ k_ra8_rsip_aes_mode_cbc
CBC.
@ k_ra8_rsip_aes_mode_cmac
CMAC.
@ k_ra8_rsip_aes_mode_gcm
GCM (AEAD).
@ k_ra8_rsip_aes_mode_ccm
CCM (AEAD).
@ k_ra8_rsip_trng_word_bytes
Bytes per TRNG read.
@ k_ra8_rsip_aes_block_bytes
AES block = 128 bits.
@ k_ra8_rsip_aes192_key_bytes
AES-192 key length.
@ k_ra8_rsip_chacha_key_bytes
ChaCha20 256-bit key.
@ k_ra8_rsip_aes256_key_bytes
AES-256 key length.
@ k_ra8_rsip_aes128_key_bytes
AES-128 key length.
@ k_ra8_rsip_mask_isr_done
ISR.DONE bit.
ra8_rsip_off_t
Byte offsets of every register the HAL touches.
@ k_ra8_rsip_off_mbox_ret
Completion code from engine.
@ k_ra8_rsip_off_data_out0
Data output lane 0.
@ k_ra8_rsip_off_sym_ctrl
Cipher command (mode|dir|alg).
@ k_ra8_rsip_off_oem_iv
OEM install IV.
@ k_ra8_rsip_off_isr
Interrupt status (W1C).
@ k_ra8_rsip_off_data_in0
Data input lane 0.
@ k_ra8_rsip_off_sym_iv3
IV / nonce lane 3.
@ k_ra8_rsip_off_sym_keyh
Cipher key-handle slot.
@ k_ra8_rsip_off_sym_iv1
IV / nonce lane 1.
@ k_ra8_rsip_off_sym_tag
AEAD authentication tag.
@ k_ra8_rsip_off_mbox_op
Opcode written by host.
@ k_ra8_rsip_off_sym_aad_len
AEAD AAD length (bytes).
@ k_ra8_rsip_off_oem_arg
OEM install argument descriptor.
@ k_ra8_rsip_off_oem_ctrl
OEM install command word.
@ k_ra8_rsip_off_key_stage
Wrapped-key load port.
@ k_ra8_rsip_off_sym_iv0
IV / nonce lane 0.
@ k_ra8_rsip_off_sym_aad_in
AEAD additional-data input.
@ k_ra8_rsip_off_sym_pt_len
AEAD plaintext length (bytes).
@ k_ra8_rsip_off_sym_iv2
IV / nonce lane 2.
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.