ra8-firmware 0.1.0
Bare-metal firmware for the Renesas RA8 family (RA8D2 / RA8P1)
Loading...
Searching...
No Matches
ra8_psa_crypto_fake.c
Go to the documentation of this file.
1
27
28#include <stddef.h>
29#include <stdint.h>
30#include <string.h>
31
32#include "ra8_err.h"
33#include "ra8_psa_crypto.h"
35
36#ifdef RA8_OFF_TARGET
37
38/* ===========================================================================
39 * Off-target crypto primitives
40 * ===========================================================================
41 *
42 * Real SHA-256 + tiny stand-ins for AES-GCM and ECDSA. These are
43 * exercised by the host unit tests and never run on the target.
44 */
45
46/* -- SHA-256 (FIPS 180-4 reference) ---------------------------------------- */
47
49static const uint32_t k_sha256_round_const[k_ra8_psa_sha256_schedule_len] = {
50 0x428a2f98U, 0x71374491U, 0xb5c0fbcfU, 0xe9b5dba5U, 0x3956c25bU, 0x59f111f1U, 0x923f82a4U,
51 0xab1c5ed5U, 0xd807aa98U, 0x12835b01U, 0x243185beU, 0x550c7dc3U, 0x72be5d74U, 0x80deb1feU,
52 0x9bdc06a7U, 0xc19bf174U, 0xe49b69c1U, 0xefbe4786U, 0x0fc19dc6U, 0x240ca1ccU, 0x2de92c6fU,
53 0x4a7484aaU, 0x5cb0a9dcU, 0x76f988daU, 0x983e5152U, 0xa831c66dU, 0xb00327c8U, 0xbf597fc7U,
54 0xc6e00bf3U, 0xd5a79147U, 0x06ca6351U, 0x14292967U, 0x27b70a85U, 0x2e1b2138U, 0x4d2c6dfcU,
55 0x53380d13U, 0x650a7354U, 0x766a0abbU, 0x81c2c92eU, 0x92722c85U, 0xa2bfe8a1U, 0xa81a664bU,
56 0xc24b8b70U, 0xc76c51a3U, 0xd192e819U, 0xd6990624U, 0xf40e3585U, 0x106aa070U, 0x19a4c116U,
57 0x1e376c08U, 0x2748774cU, 0x34b0bcb5U, 0x391c0cb3U, 0x4ed8aa4aU, 0x5b9cca4fU, 0x682e6ff3U,
58 0x748f82eeU, 0x78a5636fU, 0x84c87814U, 0x8cc70208U, 0x90befffaU, 0xa4506cebU, 0xbef9a3f7U,
59 0xc67178f2U,
60};
61
62/* Sha256 rotr -- see implementation for details. */
63static inline uint32_t internal_sha256_rotr(uint32_t x, uint32_t n)
64{
65 return (x >> n) | (x << (k_ra8_psa_word_bits - n));
66}
67
68/* Build the 64-word message schedule W[] from a single block -- see implementation for details. */
69static void internal_sha256_schedule(uint32_t schedule[k_ra8_psa_sha256_schedule_len],
70 const uint8_t block[k_ra8_psa_sha256_block_bytes])
71{
72 for (uint32_t i = 0U; i < (uint32_t)k_ra8_psa_sha256_init_words; ++i) {
73 schedule[i] =
74 ((uint32_t)block[(i * (uint32_t)k_ra8_psa_bytes_per_word) + 0U] << k_ra8_psa_shift_b3) |
75 ((uint32_t)block[(i * (uint32_t)k_ra8_psa_bytes_per_word) + 1U] << k_ra8_psa_shift_b2) |
76 ((uint32_t)block[(i * (uint32_t)k_ra8_psa_bytes_per_word) + 2U] << k_ra8_psa_shift_b1) |
77 ((uint32_t)block[(i * (uint32_t)k_ra8_psa_bytes_per_word) + 3U]);
78 }
79 for (uint32_t i = (uint32_t)k_ra8_psa_sha256_init_words;
81 ++i) {
82 const uint32_t w15 = schedule[i - (uint32_t)k_ra8_psa_w_back_15];
83 const uint32_t w2 = schedule[i - (uint32_t)k_ra8_psa_w_back_2];
84 const uint32_t s0 = internal_sha256_rotr(w15, k_ra8_psa_rot_s0_a) ^
85 internal_sha256_rotr(w15, k_ra8_psa_rot_s0_b) ^ (w15 >> k_ra8_psa_shr_s0);
86 const uint32_t s1 = internal_sha256_rotr(w2, k_ra8_psa_rot_s1_a) ^
87 internal_sha256_rotr(w2, k_ra8_psa_rot_s1_b) ^ (w2 >> k_ra8_psa_shr_s1);
88 schedule[i] = schedule[i - (uint32_t)k_ra8_psa_w_back_16] + s0 +
89 schedule[i - (uint32_t)k_ra8_psa_w_back_7] + s1;
90 }
91}
92
93/* Run the 64 SHA-256 compression rounds, updating ``state`` in place -- see implementation for details. */
94static void internal_sha256_rounds(uint32_t state[k_ra8_psa_sha256_state_words],
95 const uint32_t schedule[k_ra8_psa_sha256_schedule_len])
96{
97 uint32_t a = state[k_ra8_psa_state_idx_a];
98 uint32_t b = state[k_ra8_psa_state_idx_b];
99 uint32_t c = state[k_ra8_psa_state_idx_c];
100 uint32_t d = state[k_ra8_psa_state_idx_d];
101 uint32_t e = state[k_ra8_psa_state_idx_e];
102 uint32_t f = state[k_ra8_psa_state_idx_f];
103 uint32_t g = state[k_ra8_psa_state_idx_g];
104 uint32_t h = state[k_ra8_psa_state_idx_h];
105 for (uint32_t i = 0U; i < (uint32_t)k_ra8_psa_sha256_schedule_len; ++i) {
106 const uint32_t big_sigma1 = internal_sha256_rotr(e, k_ra8_psa_rot_e_a) ^
107 internal_sha256_rotr(e, k_ra8_psa_rot_e_b) ^
108 internal_sha256_rotr(e, k_ra8_psa_rot_e_c);
109 const uint32_t ch = (e & f) ^ ((~e) & g);
110 const uint32_t temp1 = h + big_sigma1 + ch + k_sha256_round_const[i] + schedule[i];
111 const uint32_t big_sigma0 = internal_sha256_rotr(a, k_ra8_psa_rot_a_a) ^
112 internal_sha256_rotr(a, k_ra8_psa_rot_a_b) ^
113 internal_sha256_rotr(a, k_ra8_psa_rot_a_c);
114 const uint32_t maj = (a & b) ^ (a & c) ^ (b & c);
115 const uint32_t temp2 = big_sigma0 + maj;
116 h = g;
117 g = f;
118 f = e;
119 e = d + temp1;
120 d = c;
121 c = b;
122 b = a;
123 a = temp1 + temp2;
124 }
125 state[k_ra8_psa_state_idx_a] += a;
126 state[k_ra8_psa_state_idx_b] += b;
127 state[k_ra8_psa_state_idx_c] += c;
128 state[k_ra8_psa_state_idx_d] += d;
129 state[k_ra8_psa_state_idx_e] += e;
130 state[k_ra8_psa_state_idx_f] += f;
131 state[k_ra8_psa_state_idx_g] += g;
132 state[k_ra8_psa_state_idx_h] += h;
133}
134
135/* Process one 64-byte block into the hash ``state`` -- see implementation for details. */
136static void internal_sha256_block(uint32_t state[k_ra8_psa_sha256_state_words],
137 const uint8_t block[k_ra8_psa_sha256_block_bytes])
138{
139 uint32_t schedule[k_ra8_psa_sha256_schedule_len];
140 internal_sha256_schedule(schedule, block);
141 internal_sha256_rounds(state, schedule);
142}
143
144void ra8_psa_fake_sha256_oneshot(const uint8_t* in,
145 size_t in_len,
146 uint8_t out[k_ra8_psa_sha256_len])
147{
148 uint32_t state[k_ra8_psa_sha256_state_words] = {
157 };
158
159 /* Process complete blocks. */
160 const size_t complete_blocks = in_len / (size_t)k_ra8_psa_sha256_block_bytes;
161 const size_t remaining = in_len - (complete_blocks * (size_t)k_ra8_psa_sha256_block_bytes);
162 const uint8_t* p = in;
163 for (size_t b = 0U; b < complete_blocks; ++b) {
164 internal_sha256_block(state, p);
165 p += (size_t)k_ra8_psa_sha256_block_bytes;
166 }
167
168 /* Final block(s) with padding. ``remaining`` is guaranteed < 64 by the
169 * arithmetic above; the explicit clamp keeps clang-analyzer's bound
170 * tracking happy when reading the tail byte-copy loop. */
171 uint8_t tail[k_ra8_psa_sha256_pad_buf_len] = {};
172 const size_t tail_copy_len = (remaining < (size_t)k_ra8_psa_sha256_block_bytes)
173 ? remaining
174 : (size_t)k_ra8_psa_sha256_block_bytes - 1U;
175 /* memcpy's source is declared nonnull; for an empty input ``p`` may be NULL
176 * (and ``tail_copy_len`` is then 0), so skip the otherwise-UB call. */
177 if (tail_copy_len > 0U) {
178 (void)memcpy(tail, p, tail_copy_len);
179 }
180 tail[tail_copy_len] = (uint8_t)k_ra8_psa_pad_marker;
181 const size_t tail_blocks = (remaining < (size_t)k_ra8_psa_sha256_pad_threshold) ? 1U : 2U;
182 const uint64_t bitlen = (uint64_t)in_len * (uint64_t)k_ra8_psa_byte_bits;
183 const size_t tail_len = tail_blocks * (size_t)k_ra8_psa_sha256_block_bytes;
184 for (uint32_t i = 0U; i < (uint32_t)k_ra8_psa_length_field_bytes; ++i) {
185 tail[tail_len - 1U - i] = (uint8_t)(bitlen >> (i * (uint32_t)k_ra8_psa_byte_bits));
186 }
187 for (size_t b = 0U; b < tail_blocks; ++b) {
188 internal_sha256_block(state, &tail[b * (size_t)k_ra8_psa_sha256_block_bytes]);
189 }
190
191 for (uint32_t i = 0U; i < (uint32_t)k_ra8_psa_sha256_state_words; ++i) {
192 out[(i * (uint32_t)k_ra8_psa_bytes_per_word) + 0U] = (uint8_t)(state[i] >> k_ra8_psa_shift_b3);
193 out[(i * (uint32_t)k_ra8_psa_bytes_per_word) + 1U] = (uint8_t)(state[i] >> k_ra8_psa_shift_b2);
194 out[(i * (uint32_t)k_ra8_psa_bytes_per_word) + 2U] = (uint8_t)(state[i] >> k_ra8_psa_shift_b1);
195 out[(i * (uint32_t)k_ra8_psa_bytes_per_word) + 3U] = (uint8_t)(state[i]);
196 }
197}
198
225static void internal_fake_aead_tag(const uint8_t* key,
226 size_t key_len,
227 const uint8_t* nonce,
228 size_t nonce_len,
229 const uint8_t* aad,
230 size_t aad_len,
231 const uint8_t* cipher,
232 size_t cipher_len,
233 uint8_t out_tag[k_ra8_psa_gcm_tag_len])
234{
235 uint8_t buf[k_ra8_psa_fake_scratch_bytes];
236 size_t off = 0U;
237 for (size_t i = 0U; (i < key_len) && (off < sizeof(buf)); ++i) {
238 buf[off++] = key[i];
239 }
240 for (size_t i = 0U; (i < nonce_len) && (off < sizeof(buf)); ++i) {
241 buf[off++] = nonce[i];
242 }
243 for (size_t i = 0U; (i < aad_len) && (off < sizeof(buf)); ++i) {
244 buf[off++] = aad[i];
245 }
246 for (size_t i = 0U; (i < cipher_len) && (off < sizeof(buf)); ++i) {
247 buf[off++] = cipher[i];
248 }
249 uint8_t digest[k_ra8_psa_sha256_len];
250 ra8_psa_fake_sha256_oneshot(buf, off, digest);
251 for (uint32_t i = 0U; i < (uint32_t)k_ra8_psa_gcm_tag_len; ++i) {
252 out_tag[i] = digest[i];
253 }
254}
255
276static void internal_fake_keystream(const uint8_t* key,
277 size_t key_len,
278 const uint8_t* nonce,
279 size_t nonce_len,
280 uint8_t* dst,
281 size_t len)
282{
283 uint8_t seed[k_ra8_psa_fake_scratch_bytes];
284 size_t off = 0U;
285 for (size_t i = 0U; (i < key_len) && (off < sizeof(seed)); ++i) {
286 seed[off++] = key[i];
287 }
288 for (size_t i = 0U; (i < nonce_len) && (off < sizeof(seed)); ++i) {
289 seed[off++] = nonce[i];
290 }
291 uint8_t block[k_ra8_psa_sha256_len];
292 uint32_t counter = 0U;
293 size_t produced = 0U;
294 while (produced < len) {
295 seed[off] = (uint8_t)(counter >> k_ra8_psa_shift_b3);
296 seed[off + 1U] = (uint8_t)(counter >> k_ra8_psa_shift_b2);
297 seed[off + 2U] = (uint8_t)(counter >> k_ra8_psa_shift_b1);
298 seed[off + 3U] = (uint8_t)counter;
299 ra8_psa_fake_sha256_oneshot(seed, off + (size_t)k_ra8_psa_bytes_per_word, block);
300 const size_t take = ((len - produced) < (size_t)k_ra8_psa_sha256_len)
301 ? (len - produced)
302 : (size_t)k_ra8_psa_sha256_len;
303 for (size_t i = 0U; i < take; ++i) {
304 dst[produced + i] = block[i];
305 }
306 produced += take;
307 ++counter;
308 }
309}
310
311ra8_err_t ra8_psa_fake_aead_encrypt(const struct ra8_psa_key_handle* slot,
312 const uint8_t* nonce,
313 size_t nonce_len,
314 const uint8_t* aad,
315 size_t aad_len,
316 const uint8_t* plain,
317 size_t plain_len,
318 uint8_t* out,
319 size_t* out_len)
320{
321 if (plain_len > 0U) {
323 if (plain_len > sizeof(ks)) {
325 }
326 internal_fake_keystream(slot->key, slot->key_len, nonce, nonce_len, ks, plain_len);
327 for (size_t i = 0U; i < plain_len; ++i) {
328 out[i] = (uint8_t)(plain[i] ^ ks[i]);
329 }
330 }
331 internal_fake_aead_tag(slot->key,
332 slot->key_len,
333 nonce,
334 nonce_len,
335 aad,
336 aad_len,
337 out,
338 plain_len,
339 &out[plain_len]);
340 *out_len = plain_len + (size_t)k_ra8_psa_gcm_tag_len;
341 return k_ra8_ok;
342}
343
344ra8_err_t ra8_psa_fake_aead_decrypt(const struct ra8_psa_key_handle* slot,
345 const uint8_t* nonce,
346 size_t nonce_len,
347 const uint8_t* aad,
348 size_t aad_len,
349 const uint8_t* cipher,
350 size_t plain_len,
351 uint8_t* out,
352 size_t* out_len)
353{
354 uint8_t expected_tag[k_ra8_psa_gcm_tag_len];
355 internal_fake_aead_tag(slot->key,
356 slot->key_len,
357 nonce,
358 nonce_len,
359 aad,
360 aad_len,
361 cipher,
362 plain_len,
363 expected_tag);
364 uint8_t diff = 0U;
365 for (uint32_t i = 0U; i < (uint32_t)k_ra8_psa_gcm_tag_len; ++i) {
366 diff |= (uint8_t)(expected_tag[i] ^ cipher[plain_len + i]);
367 }
368 if (diff != 0U) {
370 }
371 if (plain_len > 0U) {
373 if (plain_len > sizeof(ks)) {
375 }
376 internal_fake_keystream(slot->key, slot->key_len, nonce, nonce_len, ks, plain_len);
377 for (size_t i = 0U; i < plain_len; ++i) {
378 out[i] = (uint8_t)(cipher[i] ^ ks[i]);
379 }
380 }
381 *out_len = plain_len;
382 return k_ra8_ok;
383}
384
385#endif /* RA8_OFF_TARGET */
Error Code Definitions for ra8-firmware.
@ k_ra8_err_crc_mismatch
CRC mismatch detected on received data.
Definition ra8_err.h:423
@ k_ra8_ok
Success – operation completed with all postconditions satisfied.
Definition ra8_err.h:119
@ 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
void * memcpy(void *dst, const void *src, size_t n)
Copy memory area between non-overlapping regions.
Application-level PSA Crypto facade over tf-psa-crypto.
@ k_ra8_psa_gcm_tag_len
AES-GCM authentication tag length (16 octets).
@ k_ra8_psa_sha256_len
SHA-256 digest length (RFC 6234, Section 4.1).
Module-private definitions shared across the ra8_psa_crypto TUs.
@ k_ra8_psa_shift_b2
Shift for big-endian byte 2.
@ k_ra8_psa_state_idx_d
SHA-256 working register d slot.
@ k_ra8_psa_rot_e_a
Sigma1(e) rot a.
@ k_ra8_psa_state_idx_f
SHA-256 working register f slot.
@ k_ra8_psa_w_back_2
Schedule offset W[i-2].
@ k_ra8_psa_sha256_schedule_len
Length of message schedule W[].
@ k_ra8_psa_fake_scratch_bytes
AEAD fake scratch buffer size.
@ k_ra8_psa_state_idx_e
SHA-256 working register e slot.
@ k_ra8_psa_shift_b1
Shift for big-endian byte 1.
@ k_ra8_psa_state_idx_b
SHA-256 working register b slot.
@ k_ra8_psa_sha256_block_bytes
SHA-256 message block size.
@ k_ra8_psa_word_bits
Word width in bits.
@ k_ra8_psa_rot_s0_b
sigma0(W[i-15]) rot b.
@ k_ra8_psa_rot_e_b
Sigma1(e) rot b.
@ k_ra8_psa_length_field_bytes
64-bit big-endian length tail.
@ k_ra8_psa_state_idx_a
SHA-256 working register a slot.
@ k_ra8_psa_bytes_per_word
Bytes packed per 32-bit word.
@ k_ra8_psa_sha256_pad_buf_len
Two-block padding scratch.
@ k_ra8_psa_w_back_7
Schedule offset W[i-7].
@ k_ra8_psa_byte_bits
Bits per byte.
@ k_ra8_psa_sha256_init_words
Initial copy from block to W[].
@ k_ra8_psa_rot_e_c
Sigma1(e) rot c.
@ k_ra8_psa_state_idx_g
SHA-256 working register g slot.
@ k_ra8_psa_state_idx_h
SHA-256 working register h slot.
@ k_ra8_psa_rot_a_a
Sigma0(a) rot a.
@ k_ra8_psa_shift_b3
Shift for big-endian byte 3.
@ k_ra8_psa_w_back_16
Schedule offset W[i-16].
@ k_ra8_psa_rot_s0_a
sigma0(W[i-15]) rot a.
@ k_ra8_psa_w_back_15
Schedule offset W[i-15].
@ k_ra8_psa_sha256_state_words
SHA-256 working state words.
@ k_ra8_psa_state_idx_c
SHA-256 working register c slot.
@ k_ra8_psa_rot_s1_a
sigma1(W[i-2]) rot a.
@ k_ra8_psa_shr_s0
sigma0(W[i-15]) shr.
@ k_ra8_psa_shr_s1
sigma1(W[i-2]) shr.
@ k_ra8_psa_rot_s1_b
sigma1(W[i-2]) rot b.
@ k_ra8_psa_rot_a_b
Sigma0(a) rot b.
@ k_ra8_psa_sha256_pad_threshold
If remaining < this, one tail block.
@ k_ra8_psa_rot_a_c
Sigma0(a) rot c.
@ k_ra8_psa_pad_marker
SHA-256 padding sentinel byte.
@ k_ra8_psa_sha256_h0
RA8 PSA sha256 h0.
@ k_ra8_psa_sha256_h6
RA8 PSA sha256 h6.
@ k_ra8_psa_sha256_h4
RA8 PSA sha256 h4.
@ k_ra8_psa_sha256_h7
RA8 PSA sha256 h7.
@ k_ra8_psa_sha256_h5
RA8 PSA sha256 h5.
@ k_ra8_psa_sha256_h1
RA8 PSA sha256 h1.
@ k_ra8_psa_sha256_h2
RA8 PSA sha256 h2.
@ k_ra8_psa_sha256_h3
RA8 PSA sha256 h3.
Forward declaration of the static-pool slot type.
uint8_t key[k_ra8_psa_max_key_bytes]
Raw key material (fake).
size_t key_len
Bytes valid in key.