ra8-firmware 0.1.0
Bare-metal firmware for the Renesas RA8 family (RA8D2 / RA8P1)
Loading...
Searching...
No Matches
main.c
Go to the documentation of this file.
1
25
26#include <stdint.h>
27#include <string.h>
28
29#include "mbedtls/memory_buffer_alloc.h"
30#include "psa/crypto.h"
31#include "ra8_board_ek_ra8d2.h"
32#include "ra8_boot_entry.h"
33#include "ra8_cgc.h"
34#include "ra8_err.h"
35#include "ra8_isr.h"
36#include "ra8_time.h"
37
39typedef enum : uint32_t {
40 k_kat_baud = 115200U,
42 k_kat_heap_bytes = 0x10000U,
44
46typedef enum : uint8_t {
47 k_sha_len = 32U,
48 k_gcm_key = 16U,
50 k_gcm_pt = 64U,
51 k_gcm_ct = 80U,
52 k_ec_point = 65U,
53 k_ec_sig = 64U,
54 k_ec_coord = 32U,
55 k_abc_len = 3U,
57 k_hex_ten = 10U,
60
61static const uint8_t k_kat_msg_ok[] = "psa crypto: KAT OK\r\n";
62static const uint8_t k_kat_msg_fail[] = "psa crypto: KAT FAIL\r\n";
63
64/* Boot-path diagnostics. */
65static const uint8_t k_kat_diag_boot[] = "psa: boot (console up)\r\n";
66static const uint8_t k_kat_diag_init_fail[] = "psa: crypto_init FAIL\r\n";
67static const uint8_t k_kat_diag_init_ok[] = "psa: crypto_init ok\r\n";
68
71
73static uint8_t hex_nibble(char c)
74{
75 uint8_t v = 0U;
76 if (c >= 'a') {
77 v = (uint8_t)((c - 'a') + (int)k_hex_ten);
78 } else if (c >= 'A') {
79 v = (uint8_t)((c - 'A') + (int)k_hex_ten);
80 } else {
81 v = (uint8_t)(c - '0');
82 }
83 return v;
84}
85
87static void unhex(const char* hex, uint8_t* out, size_t n)
88{
89 for (size_t i = 0U; i < n; ++i) {
90 uint8_t hi = hex_nibble(hex[2U * i]);
91 uint8_t lo = hex_nibble(hex[(2U * i) + 1U]);
92 out[i] = (uint8_t)((int)hi << (int)k_hex_shift) | lo;
93 }
94}
95
97static bool kat_sha256(void)
98{
99 uint8_t want[k_sha_len];
100 unhex("ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad", want, k_sha_len);
101 uint8_t got[k_sha_len];
102 size_t got_len = 0U;
103 psa_status_t st = psa_hash_compute(PSA_ALG_SHA_256,
104 (const uint8_t*)"abc",
105 (size_t)k_abc_len,
106 got,
107 sizeof(got),
108 &got_len);
109 return (st == PSA_SUCCESS) && (got_len == (size_t)k_sha_len) &&
110 (memcmp(got, want, k_sha_len) == 0);
111}
112
114static bool
115gcm_enc_ok(psa_key_id_t kid, const uint8_t* nonce, const uint8_t* pt, const uint8_t* want_ct)
116{
117 uint8_t ct[k_gcm_ct];
118 size_t n = 0U;
119 if (psa_aead_encrypt(kid,
120 PSA_ALG_GCM,
121 nonce,
123 nullptr,
124 0U,
125 pt,
126 k_gcm_pt,
127 ct,
128 sizeof(ct),
129 &n) != PSA_SUCCESS) {
130 return false;
131 }
132 if (n != (size_t)k_gcm_ct) {
133 return false;
134 }
135 return memcmp(ct, want_ct, k_gcm_ct) == 0;
136}
137
139static bool
140gcm_dec_ok(psa_key_id_t kid, const uint8_t* nonce, const uint8_t* want_ct, const uint8_t* pt)
141{
142 uint8_t dec[k_gcm_pt];
143 size_t n = 0U;
144 if (psa_aead_decrypt(kid,
145 PSA_ALG_GCM,
146 nonce,
148 nullptr,
149 0U,
150 want_ct,
151 k_gcm_ct,
152 dec,
153 sizeof(dec),
154 &n) != PSA_SUCCESS) {
155 return false;
156 }
157 if (n != (size_t)k_gcm_pt) {
158 return false;
159 }
160 return memcmp(dec, pt, k_gcm_pt) == 0;
161}
162
164static bool kat_aes_gcm(void)
165{
166 uint8_t key[k_gcm_key];
167 unhex("feffe9928665731c6d6a8f9467308308", key, k_gcm_key);
168 uint8_t nonce[k_gcm_nonce];
169 unhex("cafebabefacedbaddecaf888", nonce, k_gcm_nonce);
170 uint8_t pt[k_gcm_pt];
171 unhex("d9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a721c3c0c95956809532fcf0e24"
172 "49a6b525b16aedf5aa0de657ba637b391aafd255",
173 pt,
174 k_gcm_pt);
175 uint8_t want_ct[k_gcm_ct];
176 unhex("42831ec2217774244b7221b784d0d49ce3aa212f2c02a4e035c17e2329aca12e21d514b25466931c7d8f6a5a"
177 "ac84aa051ba30b396a0aac973d58e091473f59854d5c2af327cd64a62cf35abd2ba6fab4",
178 want_ct,
179 k_gcm_ct);
180
181 psa_key_attributes_t attr = PSA_KEY_ATTRIBUTES_INIT;
182 psa_set_key_usage_flags(&attr, PSA_KEY_USAGE_ENCRYPT | PSA_KEY_USAGE_DECRYPT);
183 psa_set_key_algorithm(&attr, PSA_ALG_GCM);
184 psa_set_key_type(&attr, PSA_KEY_TYPE_AES);
185 psa_key_id_t kid = 0;
186 if (psa_import_key(&attr, key, sizeof(key), &kid) != PSA_SUCCESS) {
187 return false;
188 }
189
190 bool ok = gcm_enc_ok(kid, nonce, pt, want_ct);
191 if (!gcm_dec_ok(kid, nonce, want_ct, pt)) {
192 ok = false;
193 }
194 (void)psa_destroy_key(kid);
195 return ok;
196}
197
199static bool kat_ecdsa_p256(void)
200{
201 uint8_t pub[k_ec_point];
202 pub[0] = 0x04U;
203 unhex("60FED4BA255A9D31C961EB74C6356D68C049B8923B61FA6CE669622E60F29FB6",
204 &pub[1],
205 (size_t)k_ec_coord);
206 unhex("7903FE1008B8BC99A41AE9E95628BC64F2F1B20C2D7E9F5177A3C294D4462299",
207 &pub[1U + (size_t)k_ec_coord],
208 (size_t)k_ec_coord);
209 uint8_t sig[k_ec_sig];
210 unhex("EFD48B2AACB6A8FD1140DD9CD45E81D69D2C877B56AAF991C34D0EA84EAF3716",
211 &sig[0],
212 (size_t)k_ec_coord);
213 unhex("F7CB1C942D657C41D436C7A1B6E29F65F3E900DBB9AFF4064DC4AB2F843ACDA8",
214 &sig[(size_t)k_ec_coord],
215 (size_t)k_ec_coord);
216
217 uint8_t hash[k_sha_len];
218 size_t hl = 0U;
219 (void)psa_hash_compute(PSA_ALG_SHA_256,
220 (const uint8_t*)"sample",
221 (size_t)k_smpl_len,
222 hash,
223 sizeof(hash),
224 &hl);
225
226 psa_key_attributes_t attr = PSA_KEY_ATTRIBUTES_INIT;
227 psa_set_key_usage_flags(&attr, PSA_KEY_USAGE_VERIFY_HASH);
228 psa_set_key_algorithm(&attr, PSA_ALG_ECDSA(PSA_ALG_SHA_256));
229 psa_set_key_type(&attr, PSA_KEY_TYPE_ECC_PUBLIC_KEY(PSA_ECC_FAMILY_SECP_R1));
230 psa_key_id_t kid = 0;
231 if (psa_import_key(&attr, pub, sizeof(pub), &kid) != PSA_SUCCESS) {
232 return false;
233 }
234
235 bool ok = true;
236 if (psa_verify_hash(kid, PSA_ALG_ECDSA(PSA_ALG_SHA_256), hash, sizeof(hash), sig, sizeof(sig)) !=
237 PSA_SUCCESS) {
238 ok = false;
239 }
240 sig[0] ^= 0x01U; /* flip one bit -> must be rejected */
241 if (psa_verify_hash(kid, PSA_ALG_ECDSA(PSA_ALG_SHA_256), hash, sizeof(hash), sig, sizeof(sig)) !=
242 PSA_ERROR_INVALID_SIGNATURE) {
243 ok = false;
244 }
245 (void)psa_destroy_key(kid);
246 return ok;
247}
248
249static void kat_panic_halt(void)
250{
251 while (1) {
252 __asm__ volatile("wfi");
253 }
254}
255
256static void kat_setup_or_halt(void)
257{
258 uint32_t cpuclk0_hz = 0U;
259 if (ra8_cgc_init() != k_ra8_ok) {
261 }
264 }
265 if (ra8_time_init(cpuclk0_hz) != k_ra8_ok) {
267 }
270 }
273 }
276 }
277 (void)ra8_board_uart_console_write(k_kat_diag_boot, (size_t)(sizeof(k_kat_diag_boot) - 1U));
278 mbedtls_memory_buffer_alloc_init(s_kat_heap, sizeof(s_kat_heap));
279 if (psa_crypto_init() != PSA_SUCCESS) {
281 (size_t)(sizeof(k_kat_diag_init_fail) - 1U));
283 }
285}
286
287void main(void)
288{
291
292 while (1) {
293 bool ok = true;
294 if (!kat_sha256()) {
295 ok = false;
296 }
297 if (!kat_aes_gcm()) {
298 ok = false;
299 }
300 if (!kat_ecdsa_p256()) {
301 ok = false;
302 }
303
304 if (ok) {
305 (void)ra8_board_uart_console_write(k_kat_msg_ok, (size_t)(sizeof(k_kat_msg_ok) - 1U));
307 } else {
308 (void)ra8_board_uart_console_write(k_kat_msg_fail, (size_t)(sizeof(k_kat_msg_fail) - 1U));
310 }
312 }
314}
void main(void)
Secure fallback main entry point.
Definition main.c:37
static const uint8_t k_kat_diag_init_ok[]
Definition main.c:67
static bool gcm_dec_ok(psa_key_id_t kid, const uint8_t *nonce, const uint8_t *want_ct, const uint8_t *pt)
AES-128-GCM decrypt of want_ct under kid must equal pt.
Definition main.c:140
static bool kat_aes_gcm(void)
GCM spec Test Case 3: AES-128-GCM encrypt then decrypt round-trip.
Definition main.c:164
static bool kat_sha256(void)
FIPS 180-4 SHA-256("abc").
Definition main.c:97
static uint8_t s_kat_heap[k_kat_heap_bytes]
Static heap tf-psa's mbedtls_calloc draws from (no libc heap on target).
Definition main.c:70
kat_const_t
Demo tunables.
Definition main.c:39
@ k_kat_period_ms
Kat period ms.
Definition main.c:41
@ k_kat_heap_bytes
64 KiB static heap for tf-psa mbedtls_calloc.
Definition main.c:42
@ k_kat_baud
Kat baud.
Definition main.c:40
kat_size_t
Buffer/length sizing constants for the vectors.
Definition main.c:46
@ k_hex_ten
Hex digit A/a == 10.
Definition main.c:57
@ k_gcm_ct
64 ciphertext + 16 tag.
Definition main.c:51
@ k_hex_shift
High-nibble shift.
Definition main.c:58
@ k_ec_sig
r || s.
Definition main.c:53
@ k_gcm_pt
Gcm pt.
Definition main.c:50
@ k_abc_len
strlen("abc").
Definition main.c:55
@ k_sha_len
SHA length.
Definition main.c:47
@ k_gcm_nonce
Gcm nonce.
Definition main.c:49
@ k_ec_point
0x04 || X || Y.
Definition main.c:52
@ k_smpl_len
strlen("sample").
Definition main.c:56
@ k_gcm_key
Gcm key.
Definition main.c:48
@ k_ec_coord
P-256 coordinate width.
Definition main.c:54
static const uint8_t k_kat_diag_boot[]
Definition main.c:65
static const uint8_t k_kat_diag_init_fail[]
Definition main.c:66
static uint8_t hex_nibble(char c)
One hex digit -> nibble (ASCII order: '0'-'9' < 'A'-'F' < 'a'-'f').
Definition main.c:73
static void kat_panic_halt(void)
Definition main.c:249
static bool gcm_enc_ok(psa_key_id_t kid, const uint8_t *nonce, const uint8_t *pt, const uint8_t *want_ct)
AES-128-GCM encrypt of pt under kid must equal want_ct.
Definition main.c:115
static const uint8_t k_kat_msg_ok[]
Definition main.c:61
static bool kat_ecdsa_p256(void)
RFC 6979 A.2.5 ECDSA-P256/SHA-256 verify of "sample" + a tamper check.
Definition main.c:199
static const uint8_t k_kat_msg_fail[]
Definition main.c:62
static void unhex(const char *hex, uint8_t *out, size_t n)
Decode 2*n hex chars into out (n bytes).
Definition main.c:87
static void kat_setup_or_halt(void)
Definition main.c:256
Board-support layer for the Renesas EK-RA8D2 v1 evaluation kit.
ra8_err_t ra8_board_led_toggle(ra8_board_led_id_t led)
Toggle led's output state.
ra8_err_t ra8_board_led_init(ra8_board_led_id_t led)
Configure led as a digital output, initial level low (off).
@ k_ra8_board_led2
LED2, GREEN, P303 (jumper E26).
@ k_ra8_board_led1
LED1, BLUE, P600 (jumper E27).
ra8_err_t ra8_board_uart_console_write(const uint8_t *data, size_t len)
Polled blocking write to the J-Link OB VCOM console.
ra8_err_t ra8_board_uart_console_init(uint32_t baud)
Configure SCI8 + PD02/PD03 as the debug-console UART.
Boot entry points shared between a vector table and its startup code.
High-level Clock Generation Circuit driver.
ra8_err_t ra8_cgc_get_clock_hz(ra8_clock_id_t id, uint32_t *out_hz)
Query the current frequency of a clock-tree domain.
Definition ra8_cgc.c:132
@ k_ra8_clock_id_cpuclk0
Cortex-M85 CPUCLK0.
Definition ra8_cgc.h:70
ra8_err_t ra8_cgc_init(void)
Configure the clock tree to a safe default.
Definition ra8_cgc.c:727
Error Code Definitions for ra8-firmware.
@ k_ra8_ok
Success – operation completed with all postconditions satisfied.
Definition ra8_err.h:119
int memcmp(const void *a, const void *b, size_t n)
Compare bytes in two memory areas.
NVIC + ICU IELSR allocator.
void ra8_isr_globals_enable(void)
Globally enable maskable interrupts (PRIMASK = 0).
Definition ra8_isr.c:439
SysTick-based tick counter, delay and timestamp helpers.
ra8_err_t ra8_time_init(uint32_t cpu_hz)
Initialise SysTick for a 1 kHz tick interrupt.
Definition ra8_time.c:59
void ra8_delay_ms(uint32_t ms)
Busy-wait for at least ms milliseconds.
Definition ra8_time.c:129