ra8-firmware 0.1.0
Bare-metal firmware for the Renesas RA8 family (RA8D2 / RA8P1)
Loading...
Searching...
No Matches
ra8_rsip_ecc.c
Go to the documentation of this file.
1
37
38#include <stdint.h>
39
40#include "ra8_attributes.h"
41#include "ra8_check.h"
42#include "ra8_err.h"
43#include "ra8_log.h"
44#include "ra8_rsip.h"
46#include "ra8_rsip_internal.h"
47#include "ra8_rsip_regs.h"
48
60static const char* s_tag = "RSIP";
61
62/*
63 * The RSIP-E50D asymmetric signature / key-agreement family (ECDSA sign /
64 * verify, ECDH, Ed25519 PureEdDSA) is NOT backed by a documented register
65 * interface on this silicon. HUM Ch 52 "Renesas Secure IP (RSIP-E50D)" is a
66 * six-page feature overview (p 3302-3307) with no command-register map; the
67 * vendor engine is driven through an encrypted firmware mailbox, not the MMIO
68 * opcodes modelled below. The command-path bodies here only round-trip the
69 * host register fake; they do NOT compute a real ECDSA / ECDH / RFC 8032
70 * result. They compile only under the insecure-stub / off-target guard so a
71 * production image gets the fail-closed #else and can never mistake these
72 * bytes for a valid signature or shared secret. The real ECDSA-P256 / ECDH /
73 * Ed25519 backend is tf-psa-crypto on the M85, silicon-proven in
74 * psa_crypto_hil (issues #214 + #181). The register pokes below therefore
75 * carry NO HUM citation: there is no real register map to cite.
76 */
77#if defined(RA8_INSECURE_STUB_CRYPTO) || defined(RA8_OFF_TARGET)
78
83typedef enum : uint32_t {
84 k_ra8_rsip_curve_bytes_192 = 24U,
85 k_ra8_rsip_curve_bytes_224 = 28U,
86 k_ra8_rsip_curve_bytes_256 = 32U,
87 k_ra8_rsip_curve_bytes_384 = 48U,
88 k_ra8_rsip_curve_bytes_512 = 64U,
89 k_ra8_rsip_curve_bytes_521 = 66U,
90} ra8_rsip_curve_bytes_t;
91
116static uint32_t internal_curve_bytes(ra8_rsip_curve_t curve)
117{
118 switch (curve) {
120 return k_ra8_rsip_curve_bytes_192;
122 return k_ra8_rsip_curve_bytes_224;
127 return k_ra8_rsip_curve_bytes_256;
130 return k_ra8_rsip_curve_bytes_384;
132 return k_ra8_rsip_curve_bytes_512;
134 return k_ra8_rsip_curve_bytes_521;
135 default:
136 return 0U;
137 }
138}
139
141 ra8_rsip_curve_t curve,
142 const uint8_t* digest,
143 uint32_t digest_len,
144 uint8_t* signature)
145{
146 RA8_CHECK_NULL_PTR(key, s_tag, "key must not be nullptr");
147 RA8_CHECK_NULL_PTR(digest, s_tag, "digest must not be nullptr");
148 RA8_CHECK_NULL_PTR(signature, s_tag, "signature must not be nullptr");
149 if (curve == k_ra8_rsip_curve_ed25519) {
150 /* Ed25519 is PureEdDSA (RFC 8032), not ECDSA -- routing it through
151 * the ECDSA opcode would not produce a valid signature. Callers
152 * must use ra8_rsip_eddsa_sign(). */
154 }
155 const uint32_t curve_bytes = internal_curve_bytes(curve);
156 if (curve_bytes == 0U) {
158 }
159 priv_load_handle(key);
160 *ra8_rsip_reg32(k_ra8_rsip_off_asym_curve) = (uint32_t)curve;
164
166 if (err != k_ra8_ok) {
167 return err;
168 }
169 /* (r || s) */
170 internal_asym_pull(k_ra8_rsip_off_asym_sig_out, signature, curve_bytes * 2U);
171 return k_ra8_ok;
172}
173
175 ra8_rsip_curve_t curve,
176 const uint8_t* digest,
177 uint32_t digest_len,
178 const uint8_t* signature)
179{
180 RA8_CHECK_NULL_PTR(key, s_tag, "key must not be nullptr");
181 RA8_CHECK_NULL_PTR(digest, s_tag, "digest must not be nullptr");
182 RA8_CHECK_NULL_PTR(signature, s_tag, "signature must not be nullptr");
183 if (curve == k_ra8_rsip_curve_ed25519) {
184 /* Ed25519 is PureEdDSA (RFC 8032), not ECDSA -- callers must use
185 * ra8_rsip_eddsa_verify(). */
187 }
188 const uint32_t curve_bytes = internal_curve_bytes(curve);
189 if (curve_bytes == 0U) {
191 }
192 priv_load_handle(key);
193 *ra8_rsip_reg32(k_ra8_rsip_off_asym_curve) = (uint32_t)curve;
195 internal_asym_push(k_ra8_rsip_off_asym_sig_in, signature, curve_bytes * 2U);
198
200}
201
206typedef enum : uint32_t {
207 k_ra8_rsip_ed25519_comp_bytes = 32U,
208 k_ra8_rsip_ed25519_sig_bytes = 64U,
209} ra8_rsip_ed25519_size_t;
210
212 const uint8_t* msg,
213 uint32_t msg_len,
214 uint8_t* signature)
215{
216 RA8_CHECK_NULL_PTR(key, s_tag, "key must not be nullptr");
217 RA8_CHECK_NULL_PTR(signature, s_tag, "signature must not be nullptr");
218 if ((msg == nullptr) && (msg_len != 0U)) {
219 return k_ra8_err_null_ptr;
220 }
221 if (key->alg != (uint32_t)k_ra8_rsip_oem_cmd_ecc_ed25519_priv) {
223 }
224 priv_load_handle(key);
226 /* PureEdDSA signs the message itself, not a pre-computed digest (RFC 8032). */
227 if (msg_len > 0U) {
229 }
232
234 if (err != k_ra8_ok) {
235 return err;
236 }
237 /* (R || S) */
239 signature,
240 (uint32_t)k_ra8_rsip_ed25519_sig_bytes);
241 return k_ra8_ok;
242}
243
245 const uint8_t* msg,
246 uint32_t msg_len,
247 const uint8_t* signature)
248{
249 RA8_CHECK_NULL_PTR(key, s_tag, "key must not be nullptr");
250 RA8_CHECK_NULL_PTR(signature, s_tag, "signature must not be nullptr");
251 if ((msg == nullptr) && (msg_len != 0U)) {
252 return k_ra8_err_null_ptr;
253 }
254 if (key->alg != (uint32_t)k_ra8_rsip_oem_cmd_ecc_ed25519_priv) {
256 }
257 priv_load_handle(key);
259 if (msg_len > 0U) {
261 }
262 internal_asym_push(k_ra8_rsip_off_asym_sig_in, signature, (uint32_t)k_ra8_rsip_ed25519_sig_bytes);
265
267}
268
290static void internal_ecdh_pull_shared(ra8_rsip_key_handle_t* out)
291{
292 /* The wrapped shared secret is delivered as an HMAC-SHA-256 handle. */
295 for (uint32_t w = 0U; w < out->body_words; ++w) {
297 }
299}
300
302 ra8_rsip_curve_t curve,
303 const uint8_t* peer_x,
304 const uint8_t* peer_y,
306{
307 RA8_CHECK_NULL_PTR(key, s_tag, "key must not be nullptr");
308 RA8_CHECK_NULL_PTR(peer_x, s_tag, "peer_x must not be nullptr");
309 RA8_CHECK_NULL_PTR(peer_y, s_tag, "peer_y must not be nullptr");
310 RA8_CHECK_NULL_PTR(out, s_tag, "out must not be nullptr");
311 const uint32_t curve_bytes = internal_curve_bytes(curve);
312 if (curve_bytes == 0U) {
314 }
315 priv_load_handle(key);
316 *ra8_rsip_reg32(k_ra8_rsip_off_asym_curve) = (uint32_t)curve;
317 internal_asym_push(k_ra8_rsip_off_asym_pub_x, peer_x, curve_bytes);
318 internal_asym_push(k_ra8_rsip_off_asym_pub_y, peer_y, curve_bytes);
321
323 if (err != k_ra8_ok) {
324 return err;
325 }
326 internal_ecdh_pull_shared(out);
327 return k_ra8_ok;
328}
329
330#else /* production build: neither RA8_INSECURE_STUB_CRYPTO nor RA8_OFF_TARGET */
331
332/*
333 * Fail-closed production variant. With no real RSIP asymmetric backend on this
334 * silicon, every ECDSA / ECDH / Ed25519 entry point returns a hard error
335 * (never k_ra8_ok) so a production image cannot mistake the fake
336 * command-path for a valid signature or shared secret. Callers use
337 * tf-psa-crypto (ECDSA-P256 / ECDH / PSA_ALG_PURE_EDDSA) on the M85 instead.
338 */
339
341 ra8_rsip_curve_t curve,
342 const uint8_t* digest,
343 uint32_t digest_len,
344 uint8_t* signature)
345{
346 RA8_CHECK_NULL_PTR(key, s_tag, "ecdsa_sign: key must not be nullptr");
347 RA8_CHECK_NULL_PTR(signature, s_tag, "ecdsa_sign: signature must not be nullptr");
348 (void)curve;
349 (void)digest;
350 (void)digest_len;
352}
353
355 ra8_rsip_curve_t curve,
356 const uint8_t* digest,
357 uint32_t digest_len,
358 const uint8_t* signature)
359{
360 RA8_CHECK_NULL_PTR(key, s_tag, "ecdsa_verify: key must not be nullptr");
361 RA8_CHECK_NULL_PTR(signature, s_tag, "ecdsa_verify: signature must not be nullptr");
362 (void)curve;
363 (void)digest;
364 (void)digest_len;
366}
367
369 const uint8_t* msg,
370 uint32_t msg_len,
371 uint8_t* signature)
372{
373 RA8_CHECK_NULL_PTR(key, s_tag, "eddsa_sign: key must not be nullptr");
374 RA8_CHECK_NULL_PTR(signature, s_tag, "eddsa_sign: signature must not be nullptr");
375 (void)msg;
376 (void)msg_len;
378}
379
381 const uint8_t* msg,
382 uint32_t msg_len,
383 const uint8_t* signature)
384{
385 RA8_CHECK_NULL_PTR(key, s_tag, "eddsa_verify: key must not be nullptr");
386 RA8_CHECK_NULL_PTR(signature, s_tag, "eddsa_verify: signature must not be nullptr");
387 (void)msg;
388 (void)msg_len;
390}
391
393 ra8_rsip_curve_t curve,
394 const uint8_t* peer_x,
395 const uint8_t* peer_y,
397{
398 RA8_CHECK_NULL_PTR(key, s_tag, "ecdh_compute: key must not be nullptr");
399 RA8_CHECK_NULL_PTR(out, s_tag, "ecdh_compute: out must not be nullptr");
400 (void)curve;
401 (void)peer_x;
402 (void)peer_y;
404}
405
406#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
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_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.
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).
ra8_err_t ra8_rsip_ecdsa_verify(const ra8_rsip_key_handle_t *key, ra8_rsip_curve_t curve, const uint8_t *digest, uint32_t digest_len, const uint8_t *signature)
ECDSA verify a signature with a peer public key.
ra8_err_t ra8_rsip_eddsa_sign(const ra8_rsip_key_handle_t *key, const uint8_t *msg, uint32_t msg_len, uint8_t *signature)
Ed25519 PureEdDSA sign a message (RFC 8032).
ra8_err_t ra8_rsip_ecdh_compute(const ra8_rsip_key_handle_t *key, ra8_rsip_curve_t curve, const uint8_t *peer_x, const uint8_t *peer_y, ra8_rsip_key_handle_t *out)
ECDH shared-secret derivation.
ra8_err_t ra8_rsip_ecdsa_sign(const ra8_rsip_key_handle_t *key, ra8_rsip_curve_t curve, const uint8_t *digest, uint32_t digest_len, uint8_t *signature)
ECDSA sign a digest with a wrapped private key.
ra8_err_t ra8_rsip_eddsa_verify(const ra8_rsip_key_handle_t *key, const uint8_t *msg, uint32_t msg_len, const uint8_t *signature)
Ed25519 PureEdDSA verify a signature (RFC 8032).
Cross-TU surface for the ra8_rsip driver split.
Renesas Secure IP (RSIP-E50D) register layout for the RA8D2.
@ k_ra8_rsip_handle_words_hmac_sha256
HMAC-SHA-256 wrapped key.
ra8_rsip_curve_t
ECC curve selector (HUM Ch 52.1 Table 52.1 "ECC" p 3302).
@ k_ra8_rsip_curve_secp384r1
NIST P-384.
@ k_ra8_rsip_curve_brain384r1
Brainpool P-384r1.
@ k_ra8_rsip_curve_secp521r1
NIST P-521.
@ k_ra8_rsip_curve_brain512r1
Brainpool P-512r1.
@ k_ra8_rsip_curve_brain256r1
Brainpool P-256r1.
@ k_ra8_rsip_curve_ed25519
Ed25519.
@ k_ra8_rsip_curve_secp256r1
NIST P-256.
@ k_ra8_rsip_curve_secp192r1
NIST P-192.
@ k_ra8_rsip_curve_secp256k1
secp256k1.
@ k_ra8_rsip_curve_secp224r1
NIST P-224.
@ k_ra8_rsip_oem_cmd_hmac_sha256
HMAC-SHA-256.
@ k_ra8_rsip_oem_cmd_ecc_ed25519_priv
Ed25519 private.
@ k_ra8_rsip_asym_op_ecdh_compute
ECDH shared secret.
@ k_ra8_rsip_asym_op_eddsa_verify
Ed25519 PureEdDSA verify.
@ k_ra8_rsip_asym_op_eddsa_sign
Ed25519 PureEdDSA sign.
@ k_ra8_rsip_asym_op_ecdsa_sign
ECDSA signature gen.
@ k_ra8_rsip_asym_op_ecdsa_verify
ECDSA signature ver.
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_curve
ECC curve selector.
@ k_ra8_rsip_off_asym_shared
ECDH shared-secret handle.
@ k_ra8_rsip_off_asym_pub_x
ECC peer X / RSA pubkey lane.
@ 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_pub_y
ECC peer Y lane.
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.