ra8-firmware 0.1.0
Bare-metal firmware for the Renesas RA8 family (RA8D2 / RA8P1)
Loading...
Searching...
No Matches
ra8_ota_verify.c
Go to the documentation of this file.
1
31
32#include <stdint.h>
33
34#include "ra8_attributes.h"
35#include "ra8_check.h"
36#include "ra8_err.h"
37#include "ra8_ota.h"
38#include "ra8_ota_internal.h"
39#include "ra8_secure.h"
40
42static const char* const s_tag = "ra8_ota";
43
70static ra8_err_t internal_rehash_bank(const ra8_ota_manifest_t* m, uint8_t out_digest[32])
71{
72 ra8_err_t e = g_ra8_ota_cfg.crypto.sha256_init(g_ra8_ota_cfg.crypto.ctx);
73 if (e != k_ra8_ok) {
74 return e;
75 }
76 uint32_t offset = 0U;
77 const uint32_t max_chunks = (k_ra8_ota_max_image_bytes / k_ra8_ota_chunk_bytes) + 1U;
78 for (uint32_t i = 0U; i < max_chunks; ++i) {
79 if (offset >= m->image_size_bytes) {
80 break;
81 }
82 const uint32_t remaining = m->image_size_bytes - offset;
83 const uint32_t want = (remaining < k_ra8_ota_chunk_bytes) ? remaining : k_ra8_ota_chunk_bytes;
84 e = g_ra8_ota_cfg.flash.readback(g_ra8_ota_cfg.flash.ctx,
85 g_ra8_ota_cfg.flash.inactive_bank_addr + offset,
87 want);
88 if (e != k_ra8_ok) {
89 return e;
90 }
91 e = g_ra8_ota_cfg.crypto.sha256_update(g_ra8_ota_cfg.crypto.ctx, g_ra8_ota_buf, want);
92 if (e != k_ra8_ok) {
93 return e;
94 }
95 offset += want;
96 }
97 return g_ra8_ota_cfg.crypto.sha256_final(g_ra8_ota_cfg.crypto.ctx, out_digest);
98}
99
115
150 const uint8_t* image_digest,
151 uint8_t out_bound[k_ra8_ota_sha256_bytes])
152{
153 RA8_CHECK_NULL_PTR(manifest, s_tag, "bind: manifest");
154 RA8_CHECK_NULL_PTR(image_digest, s_tag, "bind: image_digest");
155 RA8_CHECK_NULL_PTR(out_bound, s_tag, "bind: out_bound");
156
157 uint8_t size_le[k_ra8_ota_size_field_bytes] = {};
158 for (uint8_t i = 0U; i < (uint8_t)k_ra8_ota_size_field_bytes; ++i) {
159 size_le[i] =
160 (uint8_t)(manifest->image_size_bytes >> ((uint32_t)i * (uint32_t)k_ra8_ota_octet_bits));
161 }
162
163 /* Parallel arrays: the fixed-width segments hashed in order, and their byte
164 * counts. Kept in step by the static_assert below. */
165 const uint8_t* const segments[] = {
166 (const uint8_t*)manifest->version,
167 (const uint8_t*)manifest->image_url,
168 size_le,
169 image_digest,
170 };
171 const uint32_t lengths[] = {
173 (uint32_t)k_ra8_ota_url_max_bytes,
174 (uint32_t)sizeof size_le,
175 (uint32_t)k_ra8_ota_sha256_bytes,
176 };
177 static_assert(sizeof segments / sizeof segments[0] == sizeof lengths / sizeof lengths[0],
178 "segments[] and lengths[] must describe the same number of chunks");
179
180 ra8_err_t e = g_ra8_ota_cfg.crypto.sha256_init(g_ra8_ota_cfg.crypto.ctx);
181 if (e != k_ra8_ok) {
182 return e;
183 }
184 for (uint8_t i = 0U; i < (uint8_t)(sizeof segments / sizeof segments[0]); ++i) {
185 e = g_ra8_ota_cfg.crypto.sha256_update(g_ra8_ota_cfg.crypto.ctx, segments[i], lengths[i]);
186 if (e != k_ra8_ok) {
187 return e;
188 }
189 }
190 return g_ra8_ota_cfg.crypto.sha256_final(g_ra8_ota_cfg.crypto.ctx, out_bound);
191}
192
228{
231 }
232 RA8_CHECK_NULL_PTR(manifest, s_tag, "manifest");
235 }
236
237 uint8_t digest[k_ra8_ota_sha256_bytes] = {};
238 ra8_err_t e = internal_rehash_bank(manifest, digest);
239 if (e != k_ra8_ok) {
241 return e;
242 }
243 /* Constant-time compare: this digest gates the ECDSA signature check, so a
244 * data-dependent early-out would leak how many leading bytes of the expected
245 * hash matched -- a byte-at-a-time forgery primitive (T5-12). */
246 if (!ra8_ct_equal(digest, manifest->image_sha256, k_ra8_ota_sha256_bytes)) {
249 }
250 /* Bind the manifest metadata (version/url/size) into the material the ECDSA
251 * signature authenticates so a forged version (anti-rollback bypass), a
252 * redirected URL, or a changed size cannot ride a signature made over the bare
253 * image digest (T5-05). */
254 uint8_t bound[k_ra8_ota_sha256_bytes] = {};
255 e = internal_bind_manifest_material(manifest, digest, bound);
256 if (e != k_ra8_ok) {
258 return e;
259 }
260 e = g_ra8_ota_cfg.crypto.ecdsa_verify(g_ra8_ota_cfg.crypto.ctx,
261 g_ra8_ota_cfg.pubkey_handle,
262 bound,
263 manifest->signature,
264 manifest->signature_len);
265 if (e != k_ra8_ok) {
267 return k_ra8_err_hw_error;
268 }
270 return k_ra8_ok;
271}
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_crc_mismatch
CRC mismatch detected on received data.
Definition ra8_err.h:423
@ k_ra8_err_invalid_state
Module in wrong state for requested operation.
Definition ra8_err.h:161
@ k_ra8_err_not_initialized
Module not initialized – _init() not yet called successfully.
Definition ra8_err.h:235
@ k_ra8_ok
Success – operation completed with all postconditions satisfied.
Definition ra8_err.h:119
@ 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
bool g_ra8_ota_initialized
True once ra8_ota_init succeeded (shared; contract in ra8_ota_internal.h).
Definition ra8_ota.c:57
ra8_ota_state_t g_ra8_ota_state
Current state-machine value (shared; contract in ra8_ota_internal.h).
Definition ra8_ota.c:51
uint8_t g_ra8_ota_buf[k_ra8_ota_chunk_bytes]
Streaming buffer (shared; contract in ra8_ota_internal.h).
Definition ra8_ota.c:72
void priv_ota_set_state(ra8_ota_state_t new_state, ra8_err_t err)
Implementation of priv_ota_set_state() – latch state + progress fan-out.
Definition ra8_ota.c:80
ra8_ota_cfg_t g_ra8_ota_cfg
Configuration captured at init time (shared; contract in ra8_ota_internal.h).
Definition ra8_ota.c:54
Phase-5 OTA firmware-update orchestration for the RA8D2.
@ k_ra8_ota_state_error
Last operation failed; see last err.
Definition ra8_ota.h:98
@ k_ra8_ota_state_verifying
SHA-256 + ECDSA verification.
Definition ra8_ota.h:95
@ k_ra8_ota_state_committing
About to swap banks + reset.
Definition ra8_ota.h:96
@ k_ra8_ota_url_max_bytes
NUL-terminated URL upper bound.
Definition ra8_ota.h:77
@ k_ra8_ota_sha256_bytes
SHA-256 digest length.
Definition ra8_ota.h:75
@ k_ra8_ota_version_str_bytes
NUL-terminated version string.
Definition ra8_ota.h:78
@ k_ra8_ota_chunk_bytes
Download streaming chunk size in bytes.
Definition ra8_ota.h:73
@ k_ra8_ota_max_image_bytes
512 KiB upper bound per bank.
Definition ra8_ota.h:79
Test-access surface for ra8_ota internal helpers (MC/DC).
ra8_ota_bind_field_t
Fixed byte-widths bound into the OTA signature material (T5-05).
@ k_ra8_ota_size_field_bytes
Little-endian width of image_size_bytes.
@ k_ra8_ota_octet_bits
Bits per octet for the LE size spread.
static ra8_err_t internal_rehash_bank(const ra8_ota_manifest_t *m, uint8_t out_digest[32])
Re-hash the inactive bank to re-derive the digest after program.
static ra8_err_t internal_bind_manifest_material(const ra8_ota_manifest_t *manifest, const uint8_t *image_digest, uint8_t out_bound[k_ra8_ota_sha256_bytes])
Bind manifest metadata (version/url/size) into the signed digest.
ra8_err_t ra8_ota_verify_signature(const ra8_ota_manifest_t *manifest)
Verify the freshly-programmed bank against the manifest signature.
Secure-comparison primitives for the crypto / secure-boot paths.
bool ra8_ct_equal(const void *a, const void *b, size_t len)
Constant-time equality of two byte buffers.
Definition ra8_secure.c:20
Decoded representation of the server manifest.
Definition ra8_ota.h:115
uint8_t image_sha256[k_ra8_ota_sha256_bytes]
Expected digest.
Definition ra8_ota.h:119
uint16_t signature_len
Bytes used in signature.
Definition ra8_ota.h:121
char image_url[k_ra8_ota_url_max_bytes]
HTTPS URL of the image blob.
Definition ra8_ota.h:117
uint8_t signature[k_ra8_ota_signature_max_bytes]
ECDSA signature over digest.
Definition ra8_ota.h:120
uint32_t image_size_bytes
Image size on the wire.
Definition ra8_ota.h:118
char version[k_ra8_ota_version_str_bytes]
Firmware version string.
Definition ra8_ota.h:116