ra8-firmware 0.1.0
Bare-metal firmware for the Renesas RA8 family (RA8D2 / RA8P1)
Loading...
Searching...
No Matches
ra8_rsip_rsa.c
Go to the documentation of this file.
1
34
35#include <stdint.h>
36
37#include "ra8_attributes.h"
38#include "ra8_check.h"
39#include "ra8_err.h"
40#include "ra8_log.h"
41#include "ra8_rsip.h"
43#include "ra8_rsip_internal.h"
44#include "ra8_rsip_regs.h"
45
57static const char* s_tag = "RSIP";
58
59/*
60 * RSIP-E50D RSA (RSASSA sign / verify, RSAES-OAEP / PKCS1 encrypt / decrypt) is
61 * NOT backed by a documented register interface on this silicon. HUM Ch 52
62 * "Renesas Secure IP (RSIP-E50D)" is a six-page feature overview (p 3302-3307)
63 * with no asymmetric command-register map; the vendor engine is driven through
64 * an encrypted firmware mailbox, not the MMIO opcodes modelled below. The
65 * command-path bodies here only round-trip the host register fake; they do
66 * NOT compute a real RSASP1 / RFC 8017 result. They compile only under the
67 * insecure-stub / off-target guard so a production image gets the fail-closed
68 * #else and can never mistake these bytes for a valid RSA signature or
69 * ciphertext. No plain-key RSA backend ships on this part; RSA (if ever needed)
70 * is provided by tf-psa-crypto on the M85 (issues #214 + #187). The register
71 * pokes below therefore carry NO HUM citation: there is no real register map to
72 * cite.
73 */
74#if defined(RA8_INSECURE_STUB_CRYPTO) || defined(RA8_OFF_TARGET)
75
78 const uint8_t* digest,
79 uint32_t digest_len,
80 uint8_t* signature)
81{
82 RA8_CHECK_NULL_PTR(key, s_tag, "key must not be nullptr");
83 RA8_CHECK_NULL_PTR(digest, s_tag, "digest must not be nullptr");
84 RA8_CHECK_NULL_PTR(signature, s_tag, "signature must not be nullptr");
85 if ((size != k_ra8_rsip_rsa_1024) && (size != k_ra8_rsip_rsa_2048) &&
86 (size != k_ra8_rsip_rsa_3072) && (size != k_ra8_rsip_rsa_4096)) {
88 }
94
96 if (err != k_ra8_ok) {
97 return err;
98 }
99 const uint32_t sig_len = (uint32_t)size / k_ra8_rsip_byte_bits;
101 return k_ra8_ok;
102}
103
106 const uint8_t* digest,
107 uint32_t digest_len,
108 const uint8_t* signature)
109{
110 RA8_CHECK_NULL_PTR(key, s_tag, "key must not be nullptr");
111 RA8_CHECK_NULL_PTR(digest, s_tag, "digest must not be nullptr");
112 RA8_CHECK_NULL_PTR(signature, s_tag, "signature must not be nullptr");
113 if ((size != k_ra8_rsip_rsa_1024) && (size != k_ra8_rsip_rsa_2048) &&
114 (size != k_ra8_rsip_rsa_3072) && (size != k_ra8_rsip_rsa_4096)) {
116 }
117 priv_load_handle(key);
120 const uint32_t sig_len = (uint32_t)size / k_ra8_rsip_byte_bits;
124
126}
127
151static uint32_t internal_rsa_modulus_bytes(ra8_rsip_rsa_size_t size)
152{
153 switch (size) {
158 return (uint32_t)size / (uint32_t)k_ra8_rsip_byte_bits;
159 default:
160 return 0U;
161 }
162}
163
187static bool internal_rsa_pad_ok(ra8_rsip_rsa_pad_t pad)
188{
189 switch (pad) {
192 return true;
193 default:
194 return false;
195 }
196}
197
225static ra8_err_t internal_rsa_size_pad_check(ra8_rsip_rsa_size_t size,
227 uint32_t* modulus_bytes_out)
228{
229 const uint32_t modulus_bytes = internal_rsa_modulus_bytes(size);
230 if (modulus_bytes == 0U) {
232 }
233 if (!internal_rsa_pad_ok(pad)) {
235 }
236 *modulus_bytes_out = modulus_bytes;
237 return k_ra8_ok;
238}
239
273static ra8_err_t internal_rsa_dispatch(const ra8_rsip_key_handle_t* key,
276 const uint8_t* in,
277 uint32_t in_len,
279{
280 priv_load_handle(key);
282 *ra8_rsip_reg32(k_ra8_rsip_off_asym_arg) = (uint32_t)pad;
285 *ra8_rsip_reg32(k_ra8_rsip_off_mbox_op) = (uint32_t)op;
287}
288
292 const uint8_t* plaintext,
293 uint32_t plaintext_len,
294 uint8_t* ciphertext)
295{
296 RA8_CHECK_NULL_PTR(key, s_tag, "key must not be nullptr");
297 RA8_CHECK_NULL_PTR(plaintext, s_tag, "plaintext must not be nullptr");
298 RA8_CHECK_NULL_PTR(ciphertext, s_tag, "ciphertext must not be nullptr");
299 uint32_t modulus_bytes = 0U;
300 const ra8_err_t v_err = internal_rsa_size_pad_check(size, pad, &modulus_bytes);
301 if (v_err != k_ra8_ok) {
302 return v_err;
303 }
304 if (plaintext_len == 0U) {
306 }
307 if (plaintext_len > modulus_bytes) {
309 }
310 const ra8_err_t err =
311 internal_rsa_dispatch(key, size, pad, plaintext, plaintext_len, k_ra8_rsip_asym_op_rsa_encrypt);
312 if (err != k_ra8_ok) {
313 return err;
314 }
315 internal_asym_pull(k_ra8_rsip_off_asym_sig_out, ciphertext, modulus_bytes);
316 return k_ra8_ok;
317}
318
322 const uint8_t* ciphertext,
323 uint8_t* plaintext,
324 uint32_t plaintext_cap,
325 uint32_t* recovered_len)
326{
327 RA8_CHECK_NULL_PTR(key, s_tag, "key must not be nullptr");
328 RA8_CHECK_NULL_PTR(ciphertext, s_tag, "ciphertext must not be nullptr");
329 RA8_CHECK_NULL_PTR(plaintext, s_tag, "plaintext must not be nullptr");
330 RA8_CHECK_NULL_PTR(recovered_len, s_tag, "recovered_len must not be nullptr");
331 uint32_t modulus_bytes = 0U;
332 const ra8_err_t v_err = internal_rsa_size_pad_check(size, pad, &modulus_bytes);
333 if (v_err != k_ra8_ok) {
334 return v_err;
335 }
336 const ra8_err_t err = internal_rsa_dispatch(key,
337 size,
338 pad,
339 ciphertext,
340 modulus_bytes,
342 if (err != k_ra8_ok) {
343 return err;
344 }
345 /* The engine writes the unpadded message length back into ASYM_ARG. */
346 const uint32_t recovered = *ra8_rsip_reg32(k_ra8_rsip_off_asym_arg);
347 if (recovered > plaintext_cap) {
349 }
350 internal_asym_pull(k_ra8_rsip_off_asym_sig_out, plaintext, recovered);
351 *recovered_len = recovered;
352 return k_ra8_ok;
353}
354
355#else /* production build: neither RA8_INSECURE_STUB_CRYPTO nor RA8_OFF_TARGET */
356
357/*
358 * Fail-closed production variant. With no real RSIP RSA backend on this
359 * silicon, every RSASSA / RSAES entry point returns a hard error (never
360 * k_ra8_ok) so a production image cannot mistake the fake command-path for
361 * a valid RSA signature or ciphertext. Callers use tf-psa-crypto on the M85.
362 */
363
366 const uint8_t* digest,
367 uint32_t digest_len,
368 uint8_t* signature)
369{
370 RA8_CHECK_NULL_PTR(key, s_tag, "rsa_sign: key must not be nullptr");
371 RA8_CHECK_NULL_PTR(signature, s_tag, "rsa_sign: signature must not be nullptr");
372 (void)size;
373 (void)digest;
374 (void)digest_len;
376}
377
380 const uint8_t* digest,
381 uint32_t digest_len,
382 const uint8_t* signature)
383{
384 RA8_CHECK_NULL_PTR(key, s_tag, "rsa_verify: key must not be nullptr");
385 RA8_CHECK_NULL_PTR(signature, s_tag, "rsa_verify: signature must not be nullptr");
386 (void)size;
387 (void)digest;
388 (void)digest_len;
390}
391
395 const uint8_t* plaintext,
396 uint32_t plaintext_len,
397 uint8_t* ciphertext)
398{
399 RA8_CHECK_NULL_PTR(key, s_tag, "rsa_encrypt: key must not be nullptr");
400 RA8_CHECK_NULL_PTR(ciphertext, s_tag, "rsa_encrypt: ciphertext must not be nullptr");
401 (void)size;
402 (void)pad;
403 (void)plaintext;
404 (void)plaintext_len;
406}
407
411 const uint8_t* ciphertext,
412 uint8_t* plaintext,
413 uint32_t plaintext_cap,
414 uint32_t* recovered_len)
415{
416 RA8_CHECK_NULL_PTR(key, s_tag, "rsa_decrypt: key must not be nullptr");
417 RA8_CHECK_NULL_PTR(plaintext, s_tag, "rsa_decrypt: plaintext must not be nullptr");
418 RA8_CHECK_NULL_PTR(recovered_len, s_tag, "rsa_decrypt: recovered_len must not be nullptr");
419 (void)size;
420 (void)pad;
421 (void)ciphertext;
422 (void)plaintext_cap;
424}
425
426#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
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.
Renesas Secure IP (RSIP-E50D) HAL driver – public API.
Cross-TU surface shared by the RSIP asymmetric + RSA split.
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.
void priv_load_handle(const ra8_rsip_key_handle_t *handle)
Stream a wrapped-key body into the engine input FIFO.
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_byte_bits
Shift one byte.
Renesas Secure IP (RSIP-E50D) register layout for the RA8D2.
ra8_rsip_rsa_size_t
RSA key-size selector (HUM Ch 52.1 Table 52.1 "RSA" p 3302).
@ k_ra8_rsip_rsa_4096
4096-bit RSA.
@ k_ra8_rsip_rsa_1024
1024-bit RSA.
@ k_ra8_rsip_rsa_3072
3072-bit RSA.
@ k_ra8_rsip_rsa_2048
2048-bit RSA.
ra8_rsip_asym_op_t
Opcode written to ASYM_CTRL to select the operation.
@ k_ra8_rsip_asym_op_rsa_verify
RSA signature ver.
@ k_ra8_rsip_asym_op_rsa_decrypt
RSA private decrypt.
@ k_ra8_rsip_asym_op_rsa_sign
RSA signature gen.
@ k_ra8_rsip_asym_op_rsa_encrypt
RSA public encrypt.
ra8_rsip_rsa_pad_t
RSA encryption padding-scheme selector written to ASYM_ARG.
@ k_ra8_rsip_rsa_pad_oaep
RSAES-OAEP (SHA-256 MGF1).
@ k_ra8_rsip_rsa_pad_pkcs1
RSAES-PKCS1-v1_5 (legacy).
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_mask_isr_asym_done
ISR.ASYM_DONE bit.
@ k_ra8_rsip_off_asym_sig_out
Signature output lane.
@ k_ra8_rsip_off_asym_msg_in
Message / digest input port.
@ k_ra8_rsip_off_asym_arg
Argument-block descriptor.
@ k_ra8_rsip_off_mbox_op
Opcode written by host.
@ k_ra8_rsip_off_asym_ctrl
Asymmetric command word.
@ k_ra8_rsip_off_asym_sig_in
Signature input lane.
@ k_ra8_rsip_off_asym_rsa_size
RSA modulus-size selector.
ra8_err_t ra8_rsip_rsa_decrypt(const ra8_rsip_key_handle_t *key, ra8_rsip_rsa_size_t size, ra8_rsip_rsa_pad_t pad, const uint8_t *ciphertext, uint8_t *plaintext, uint32_t plaintext_cap, uint32_t *recovered_len)
RSA private-key decrypt a ciphertext (RSAES-OAEP / PKCS1).
ra8_err_t ra8_rsip_rsa_verify(const ra8_rsip_key_handle_t *key, ra8_rsip_rsa_size_t size, const uint8_t *digest, uint32_t digest_len, const uint8_t *signature)
RSA verify a signature against a digest using a wrapped pubkey.
ra8_err_t ra8_rsip_rsa_sign(const ra8_rsip_key_handle_t *key, ra8_rsip_rsa_size_t size, const uint8_t *digest, uint32_t digest_len, uint8_t *signature)
RSA sign a digest with a wrapped private key.
ra8_err_t ra8_rsip_rsa_encrypt(const ra8_rsip_key_handle_t *key, ra8_rsip_rsa_size_t size, ra8_rsip_rsa_pad_t pad, const uint8_t *plaintext, uint32_t plaintext_len, uint8_t *ciphertext)
RSA public-key encrypt a short message (RSAES-OAEP / PKCS1).
Opaque wrapped-key handle.