Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
41 commits
Select commit Hold shift + click to select a range
94d1d05
F-14097 - Correct boot pointer-validation comment
aidangarske Sep 22, 2026
428f17f
F-14098 - Clarify VNET RX token exposure
aidangarske Sep 22, 2026
b6ef58e
F-14096 - Correct secure partition privilege comments
aidangarske Sep 22, 2026
ac7ce64
F-14111 - Make queued mutex acquisition idempotent
aidangarske Sep 22, 2026
b5ae318
F-14114 - Check active coroutine stack canaries
aidangarske Sep 22, 2026
b8a584b
F-14104 - Panic on invalid wait output pointers
aidangarske Sep 22, 2026
79cce87
F-14112 - Dispatch runnable lock waiters
aidangarske Sep 22, 2026
87caad9
F-14118 - Erase shared HSM relay buffers
aidangarske Sep 22, 2026
4437d7f
F-14124 - Erase HSM client response buffers
aidangarske Sep 22, 2026
d58af40
F-14125 - Erase storage client request copies
aidangarske Sep 22, 2026
6dde2f5
F-14119 - Erase per-guest HSM relay buffers
aidangarske Sep 22, 2026
93b0b0b
F-14122 - Erase HSM state during relay recovery
aidangarske Sep 22, 2026
c2b30f7
F-14123 - Erase HSM tasklet state on fault
aidangarske Sep 22, 2026
beba8d7
F-14095 - Correct HSM fault notification comments
aidangarske Sep 22, 2026
30e3bc5
F-14109 - Restore residual virtual SysTick period
aidangarske Sep 22, 2026
f1d60ab
F-14126 - Scrub restart-clear RAM before quarantine
aidangarske Sep 22, 2026
e34bf46
F-14127 - Erase non-word-aligned guest RAM tails
aidangarske Sep 22, 2026
bd769d0
F-14108 - Release IPC resources on quarantine
aidangarske Sep 22, 2026
a424c1c
F-14101 - Address the Non-secure NVIC banks
aidangarske Sep 22, 2026
504a823
F-14102 - Support the full Secure IRQ range
aidangarske Sep 22, 2026
696be66
F-14120 - Erase flash programming words
aidangarske Sep 22, 2026
1faaa9d
F-14121 - Erase flash read-back buffers
aidangarske Sep 22, 2026
03806c6
F-14117 - Pad unaligned firmware update writes
aidangarske Sep 22, 2026
02eaf74
F-14107 - Preserve FWU state when disarm fails
aidangarske Sep 22, 2026
7971342
F-14099 - Erase vault request and plaintext buffers
aidangarske Sep 22, 2026
e11d10f
F-14100 - Erase storage request and plaintext buffers
aidangarske Sep 22, 2026
f752dfb
F-14106 - Preserve sealed removal and reject key deletion
aidangarske Sep 22, 2026
1303542
F-14106 - Cover sealed deletion recovery
aidangarske Sep 23, 2026
316d252
F-14111 - Cover queued mutex handoff
aidangarske Sep 23, 2026
849197b
F-14123 - Preserve HSM fault canary
aidangarske Sep 23, 2026
97b8895
F-14117 - Cover padded FWU writes
aidangarske Sep 23, 2026
7effa55
F-14107 - Cover failed FWU disarm
aidangarske Sep 23, 2026
be6183b
F-14127 - Keep guest RAM clearing word-efficient
aidangarske Sep 23, 2026
fd179ea
F-14100 - Keep full buffer clearing responsive
aidangarske Sep 23, 2026
2226982
F-14109 - Reset and latch guest SysTick safely
aidangarske Sep 23, 2026
143023a
F-14118 - Preserve relay flow while clearing packets
aidangarske Sep 23, 2026
6de4635
F-14111 - Correct lock-wait diagnostic comment
aidangarske Sep 23, 2026
d8b5d76
F-14123 - Keep HSM tasklet faults contained
aidangarske Sep 23, 2026
cb90aa4
F-14106 - Preserve keys during sealed delete recovery
aidangarske Sep 23, 2026
9d30f4e
Reject key deletion through vault storage remove
aidangarske Sep 23, 2026
3faf8f4
Wipe a faulted wolfHSM tasklet stack through the SPM-private stack mo…
aidangarske Oct 1, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions docs/API-Reference.md
Original file line number Diff line number Diff line change
Expand Up @@ -476,9 +476,9 @@ monotonic version. The current service supports one primary component and
commits installation at authenticated reboot. It does not offer a persistent
trial state, so `psa_fwu_accept` returns
`PSA_ERROR_NOT_SUPPORTED`.
Unlike PSA Firmware Update 1.0, the service rejects unaligned block sizes rather
than padding them and returns `PSA_ERROR_INVALID_ARGUMENT` for unknown
component IDs instead of `PSA_ERROR_DOES_NOT_EXIST`.
The service pads an unaligned block size to the backend write alignment. It
returns `PSA_ERROR_INVALID_ARGUMENT` for unknown component IDs instead of
`PSA_ERROR_DOES_NOT_EXIST`.

## Initial Attestation

Expand Down
10 changes: 5 additions & 5 deletions docs/Services.md
Original file line number Diff line number Diff line change
Expand Up @@ -152,16 +152,16 @@ exported.
## Firmware Update

`SERVICE_FWU` exposes a single-component subset of PSA Firmware Update 1.0.
Unlike the specification, it rejects unaligned block sizes instead of padding
them and returns `PSA_ERROR_INVALID_ARGUMENT` rather than
`PSA_ERROR_DOES_NOT_EXIST` for unknown component IDs. The normal flow is:
It pads an unaligned block size to the backend write alignment and returns
`PSA_ERROR_INVALID_ARGUMENT` rather than `PSA_ERROR_DOES_NOT_EXIST` for an
unknown component ID. The normal flow is:

```text
READY -> WRITING -> CANDIDATE -> STAGED -> authenticated reboot
```

Writes are copied, bounded, aligned to the target flash granularity, and staged
in the wolfBoot update partition. Finish validates the complete wolfBoot image
Writes are copied, bounded, offset-aligned, padded with erased-flash bytes when
needed, and staged in the wolfBoot update partition. Finish validates the image
header and binds the candidate version. Install checks the candidate again
against the persistent version floor loaded when the Firmware Update partition
started, then writes the wolfBoot update trigger. A reboot request is allowed
Expand Down
10 changes: 5 additions & 5 deletions docs/TF-M-Compatibility.md
Original file line number Diff line number Diff line change
Expand Up @@ -114,7 +114,7 @@ where the platform and feature set are held constant.
| Internal Trusted Storage | 1.0 | Core set/get/get-info/remove subset with the `WRITE_ONCE` lifecycle deviation below | `include/psa/internal_trusted_storage.h` and `src/services/wolfhsm/wt_hsm_vault.c` |
| Protected Storage | 1.0 | Core set/get/get-info/remove subset; optional create/set-extended absent and the `WRITE_ONCE` lifecycle deviation below applies | `include/psa/protected_storage.h` and `src/services/storage_service.c` |
| Initial Attestation | 1.0 API subset with a nonconformant RFC 9783-derived token | Token and exact-size operations are supported, but the advertised TF-M profile has the claim-semantic deviations below | `lib/wolfPSA/wolfpsa/psa/initial_attestation.h` and `src/services/initial_attestation.c` |
| Firmware Update | 1.0 subset | Single-component staging and authenticated reboot supported, with the alignment and status deviations below | `include/psa/update.h` and `src/services/fwu_service.c` |
| Firmware Update | 1.0 subset | Single-component staging and authenticated reboot supported, with the status deviation below | `include/psa/update.h` and `src/services/fwu_service.c` |
| RoT lifecycle query | FF-M 1.0 | Secure Partition only; there is no Non-secure adapter or veneer | `include/psa/lifecycle.h` and `src/arch/common/spm_sp_api.c` |
| Secure Partition signals and IRQ APIs | FF-M 1.0 plus one wolfTrust-specific beta-extension backport | The 1.0 signal APIs and `psa_eoi` are supported; only `psa_irq_enable()` is backported from the FF-M 1.1 Extension Beta, Issue 0, while `psa_irq_status_t`, `psa_irq_is_enabled`, `psa_irq_disable`, and `psa_irq_restore` are absent | `include/psa/service.h` and the Armv8-M SVC implementation |
| Guest identity | FF-M convention | Non-secure guest `N` is client `-(N + 1)` | `src/arch/armv8m/ffm_nsc.c` |
Expand All @@ -139,7 +139,7 @@ where the platform and feature set are held constant.
| The attestation token advertises `tag:psacertified.org,2023:psa#tfm` but does not implement that profile's claim semantics. | Known token-profile deviation | The boot seed is deterministic across equivalent boots; software-component measurement type and description values are reversed; signer ID hashes the literal name `wolfBoot` rather than identifying the signing key; and implementation ID hashes a software label rather than identifying the immutable PSA RoT hardware assembly. A distinct derived profile identifier is required until these claims conform to [RFC 9783](https://www.rfc-editor.org/rfc/rfc9783.html). |
| Firmware Update has no persistent trial-accept flow. | Scoped | Installation commits only after wolfBoot authenticates the swapped image at reboot; `psa_fwu_accept()` returns `PSA_ERROR_NOT_SUPPORTED`. |
| The firmware-update detached manifest is a 32-bit version word. | Scoped integration | Passing `NULL, 0` instead binds the version from the staged wolfBoot header. Other manifest encodings require an adapter. |
| Firmware Update rejects unaligned block sizes and reports unknown component IDs as `PSA_ERROR_INVALID_ARGUMENT`. | Known API deviations | PSA Firmware Update 1.0 pads unaligned final block sizes and specifies `PSA_ERROR_DOES_NOT_EXIST` for unknown component IDs. |
| Firmware Update reports unknown component IDs as `PSA_ERROR_INVALID_ARGUMENT`. | Known API deviation | PSA Firmware Update 1.0 specifies `PSA_ERROR_DOES_NOT_EXIST` for unknown component IDs. Unaligned block sizes are padded to the backend write alignment. |
| Secure memory uses no dynamic allocation. | Stronger resource policy | Fixed pools and buffers can reject excess work rather than expanding at runtime. |
| Manifests use wolfTrust JSON and generated C. | Integration difference | Existing TF-M manifests are not consumed directly. Security resources and services must be represented in the wolfTrust schema. |
| Secure Partition entry functions are bound at build time instead of being selected by each manifest's `entry_point` field. | Integration difference | The numeric field validates an executable window, but adding a service also requires a compiled entry wrapper and an explicit start call in `wt_ffm_boot_start_sched()`. |
Expand Down Expand Up @@ -187,9 +187,9 @@ actual boundary.
and manifest.
5. Check data-size assumptions against the copied IPC and service limits.
Stream update images in blocks no larger than `PSA_FWU_MAX_WRITE_SIZE`.
For wolfTrust, both the image offset and block size must be aligned to
`1 << PSA_FWU_LOG2_WRITE_ALIGN`, including the final block. This is stricter
than PSA Firmware Update 1.0, which permits padding an unaligned final block.
For wolfTrust, the image offset must be aligned to
`1 << PSA_FWU_LOG2_WRITE_ALIGN`. An unaligned final block is padded by the
service to the backend write alignment.
6. Check optional APIs before use. In particular, treat Protected Storage
create/set-extended and Firmware Update accept as unsupported.
7. Express Secure services, dependencies, memory, interrupts, restart policy,
Expand Down
4 changes: 4 additions & 0 deletions include/wolftrust/hsm_priv.h
Original file line number Diff line number Diff line change
Expand Up @@ -42,4 +42,8 @@ wt_guest_id_t wt_hsm_guest_for_tasklet(const struct wt_co *tasklet);
* NULL for an out-of-range guest. */
unsigned char *wt_hsm_priv_stack(wt_guest_id_t guest_id);

/* Zero a faulted guest's tasklet stack and guard, keeping the canary word at
* stack[0] for the post-fault switch check. */
void wt_hsm_priv_wipe_stack(wt_guest_id_t guest_id);

#endif /* WOLFTRUST_HSM_PRIV_H */
21 changes: 9 additions & 12 deletions include/wolftrust/services/hsm.h
Original file line number Diff line number Diff line change
Expand Up @@ -99,11 +99,9 @@ uint16_t wt_hsm_guest_client_id(wt_guest_id_t guest_id);
* registry can be unit-tested on the host. */
#include "wolftrust/hsm_priv.h"

/* Signal a terminal Secure-side fault for guest_id: drops the NVM lock
* if the dying tasklet was holding it, writes a WH_ERROR_ABORTED
* fatal-response into the guest's transport, and clears the ready bit
* so subsequent NSC veneers reject HSM calls from this guest. Safe to
* call from handler mode. Returns WH_ERROR_OK on success. */
/* Signal a terminal Secure-side fault for guest_id: drop held locks, invoke
* the optional fault-notification hook, erase retained tasklet state, and
* clear the ready bit. Safe from handler mode. */
int wt_hsm_signal_fault(wt_guest_id_t guest_id);

/* Drop every secure-side wolfHSM lock held by a faulted coroutine. Used by the
Expand All @@ -122,9 +120,8 @@ struct wt_mutex *wt_hsm_nvm_lock_mutex(void);
* state unusable. Fails closed — a guest whose re-init fails stays down. */
int wt_hsm_relay_reinit_servers(void);

/* Terminal-fault NS-client notifier. wt_hsm_signal_fault calls the installed
* callback; the arch transport installs its concrete notifier at boot. The
* default is a no-op so engine-less/host builds link. */
/* Terminal-fault NS-client notifier. The default is a no-op, and no current
* port installs a replacement, so this path does not notify NS clients. */
typedef int (*wt_hsm_fault_notify_fn)(wt_guest_id_t guest_id);
void wt_hsm_set_fault_notify(wt_hsm_fault_notify_fn fn);

Expand Down Expand Up @@ -155,9 +152,9 @@ int wt_hsm_vault_init(struct whNvmContext_t* nvm);
struct wt_vault_backend;
extern const struct wt_vault_backend wt_hsm_vault_backend;

/* Vault sealer (WT-FFM-0048): AES-GCM confidentiality + rollback binding for
* WT_VAULT_FLAG_SEALED objects, running entirely inside the privileged vault
* domain — the device-unique key never reaches any Secure Partition. seal
/* Vault sealer (WT-FFM-0048): AES-GCM confidentiality and rollback binding
* for WT_VAULT_FLAG_SEALED objects. Operations run in the confined vault SP,
* with the device-unique key kept in the shared keystore trust band. seal
* writes pt_len + WT_VAULT_SEAL_TAG_LEN bytes ([ciphertext][tag]); unseal
* takes ct_len >= tag length and writes ct_len - tag plaintext bytes. The
* monotonic rollback counter is the GCM nonce, so a replayed (rolled-back)
Expand Down Expand Up @@ -188,7 +185,7 @@ void wt_hsm_vault_set_sealer(const wt_vault_sealer_t* sealer);
int wt_hsm_seal_init(struct whNvmContext_t* nvm);
extern const wt_vault_sealer_t wt_hsm_sealer;

/* Shared vault directory helpers (wt_hsm_vault.c) for privileged backends:
/* Shared vault directory helpers (wt_hsm_vault.c) for confined backends:
* label-addressed lookup over the vault NVM id window, and the label
* make/flags codec. whNvmMetadata is an untagged typedef, so wh_common.h
* must be included for the real type. */
Expand Down
2 changes: 1 addition & 1 deletion include/wolftrust/services/storage_service.h
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@
* (partition, client id, uid) via the delegated sub_owner (WT-FFM-0044).
* The PS instance additionally ORs WT_VAULT_FLAG_SEALED into every request:
* AES-GCM under the device-unique wolfHSM key plus rollback binding, applied
* entirely inside the privileged vault domain (WT-FFM-0048). */
* inside the confined vault partition (WT-FFM-0048). */

/* psa_call request types (client face). Ops 1-4 are the shared ITS/PS core;
* 5-7 exist only on the PS face. */
Expand Down
17 changes: 9 additions & 8 deletions include/wolftrust/services/vault_service.h
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,8 @@
* never a caller-supplied field (WT-FFM-0044). Non-secure clients are
* refused by the manifest (nonsecure_clients = false). */

/* psa_call request types. REMOVE also destroys keys (psa_destroy_key). */
/* psa_call request types. REMOVE applies to storage objects; the current
* vault backend does not support key deletion. */
#define WT_VAULT_OP_SET 1
#define WT_VAULT_OP_GET 2
#define WT_VAULT_OP_GET_INFO 3
Expand All @@ -56,8 +57,8 @@

/* Internal flag a storage frontend ORs in (never a PSA create flag): the
* object is AES-GCM sealed under the device-unique wolfHSM key with the
* monotonic rollback counter as nonce (WT-FFM-0048). Sealing runs entirely
* inside the privileged vault domain. */
* monotonic rollback counter as nonce (WT-FFM-0048). Sealing runs inside the
* confined vault partition. */
#define WT_VAULT_FLAG_SEALED 0x10000U

/* Label marker for key objects (WT-FFM-0046). Never accepted from a storage
Expand Down Expand Up @@ -129,9 +130,9 @@ typedef struct wt_vault_backend {
psa_status_t (*remove)(int32_t owner, int32_t sub, uint64_t uid);
} wt_vault_backend_t;

/* Key-operation vtable (WT-FFM-0046): every operation executes INSIDE the
* privileged vault domain against material that never leaves it. There is
* deliberately no private-export entry point. sign/verify operate on a
/* Key-operation vtable (WT-FFM-0046): every operation executes inside the
* confined vault partition against material in its keystore trust band. There
* is deliberately no private-export entry point. sign/verify operate on a
* caller-supplied digest; encrypt frames its output [nonce][ct][tag] and
* decrypt consumes the same framing. */
typedef struct wt_vault_key_backend {
Expand All @@ -156,8 +157,8 @@ typedef struct wt_vault_key_backend {
uint8_t* out, size_t cap, size_t* out_len);
} wt_vault_key_backend_t;

/* Vault-domain randomness (WT-FFM-0054): fill out[0..len) from an RNG owned
* by the privileged vault domain, never a frontend partition. This is entropy
/* Vault randomness (WT-FFM-0054): fill out[0..len) from an RNG owned by the
* confined vault partition, never a frontend partition. This is entropy
* plumbing, kept separate from the key backend so retiring the key backend
* does not disturb the RANDOM face. */
typedef psa_status_t (*wt_vault_rng_fn)(uint8_t* out, size_t len);
Expand Down
4 changes: 2 additions & 2 deletions include/wolftrust/services/vnet_relay.h
Original file line number Diff line number Diff line change
Expand Up @@ -29,8 +29,8 @@
* (WT-FFM-0056). A non-secure guest reaches its switch port only through
* psa_connect/psa_call; the operation rides the FF-M call type and the SPM
* stamps the caller identity, which selects the port. Frame bytes cross as
* copied FF-M vectors, so pool slot/generation tokens never leave the
* secure side and cannot be forged or replayed by a guest. */
* copied FF-M vectors. RX_FETCH returns the slot/generation metadata only
* after the relay has consumed and released the corresponding token. */

/* The WT_VNET_OP_* operation codes and SID live in vnet_abi.h, shared with
* the non-secure client transport.
Expand Down
44 changes: 44 additions & 0 deletions include/wolftrust/zeroize.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
/* zeroize.h
*
* Copyright (C) 2026 wolfSSL Inc.
*
* This file is part of wolfTrust.
*
* wolfTrust is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* wolfTrust is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, see <https://www.gnu.org/licenses/>.
*/

#ifndef WOLFTRUST_ZEROIZE_H
#define WOLFTRUST_ZEROIZE_H

#include <stddef.h>

static inline void wt_forceZero(void* memory, size_t size)
Comment thread
aidangarske marked this conversation as resolved.
{
volatile unsigned char* bytes = (volatile unsigned char*)memory;

while (size >= 4U) {
bytes[0] = 0U;
bytes[1] = 0U;
bytes[2] = 0U;
bytes[3] = 0U;
bytes += 4;
size -= 4U;
}
while (size > 0U) {
*bytes++ = 0U;
size--;
}
}

#endif /* WOLFTRUST_ZEROIZE_H */
5 changes: 5 additions & 0 deletions mk/common.mk
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,7 @@ WT_HSM_PIN_NEG_PROBE ?= 0
WT_LAUNCH_DEBUG ?= 0
WT_ROLLBACK_PROBE ?= 0
WT_SP_FAULT_PROBE ?= 0
WT_HSM_FAULT_PROBE ?= 0
WT_SP_FAULT_ALWAYS_PROBE ?= 0
WT_PANIC_NEG_PROBE ?= 0
WT_VNET_NEG_PROBE ?= 0
Expand Down Expand Up @@ -178,6 +179,9 @@ endif
ifeq ($(WT_SP_FAULT_PROBE),1)
SECURE_CFLAGS += -DWT_SP_FAULT_PROBE=1
endif
ifeq ($(WT_HSM_FAULT_PROBE),1)
SECURE_CFLAGS += -DWT_HSM_FAULT_PROBE=1
endif
ifeq ($(WT_SP_FAULT_ALWAYS_PROBE),1)
SECURE_CFLAGS += -DWT_SP_FAULT_ALWAYS_PROBE=1
endif
Expand Down Expand Up @@ -1409,6 +1413,7 @@ $(BUILD_MODE_STAMP): FORCE | $(BUILD_DIR)
'WT_LAUNCH_DEBUG=$(WT_LAUNCH_DEBUG)' \
'WT_ROLLBACK_PROBE=$(WT_ROLLBACK_PROBE)' \
'WT_SP_FAULT_PROBE=$(WT_SP_FAULT_PROBE)' \
'WT_HSM_FAULT_PROBE=$(WT_HSM_FAULT_PROBE)' \
'WT_SP_FAULT_ALWAYS_PROBE=$(WT_SP_FAULT_ALWAYS_PROBE)' \
'WT_PANIC_NEG_PROBE=$(WT_PANIC_NEG_PROBE)' \
'WT_VNET_NEG_PROBE=$(WT_VNET_NEG_PROBE)' \
Expand Down
41 changes: 22 additions & 19 deletions port/stm32h563/hsm_flash.c
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
#include "wolftrust/services/fwu_service.h"
#include "wolftrust/spm_gate.h"
#include "wolftrust/arch.h"
#include "wolftrust/zeroize.h"

#include <stdbool.h>
#include <stdint.h>
Expand Down Expand Up @@ -516,6 +517,7 @@ static int wt_hsm_flash_program(void *context, uint32_t offset, uint32_t size,
g_wt_flash_first_err_sr = WT_FLASH_SR;
}
ret = wt_flash_check_errors();
wt_forceZero(word, sizeof(word));
if (ret != WH_ERROR_OK) {
break;
}
Expand Down Expand Up @@ -617,7 +619,7 @@ static int wt_hsm_flash_verify(void *context, uint32_t offset, uint32_t size,
const wt_hsm_flash_config_t *geom = wt_flash_geometry(context);
uint8_t flash_data[16];
uint32_t checked = 0u;
int ret;
int ret = WH_ERROR_OK;

if (data == NULL && size != 0u) {
return WH_ERROR_BADARGS;
Expand All @@ -629,7 +631,7 @@ static int wt_hsm_flash_verify(void *context, uint32_t offset, uint32_t size,
if (!wt_flash_range_ok(geom, offset, size)) {
return WH_ERROR_BADARGS;
}
while (checked < size) {
while (checked < size && ret == WH_ERROR_OK) {
uint32_t chunk = size - checked;

if (chunk > sizeof(flash_data)) {
Expand All @@ -638,15 +640,16 @@ static int wt_hsm_flash_verify(void *context, uint32_t offset, uint32_t size,
ret = wt_flash_read_checked(
(const uint8_t *)(geom->base + offset + checked), flash_data,
chunk);
if (ret != WH_ERROR_OK) {
return ret;
if (ret == WH_ERROR_OK &&
memcmp(flash_data, data + checked, chunk) != 0) {
ret = WH_ERROR_NOTVERIFIED;
}
if (memcmp(flash_data, data + checked, chunk) != 0) {
return WH_ERROR_NOTVERIFIED;
if (ret == WH_ERROR_OK) {
checked += chunk;
}
checked += chunk;
}
return WH_ERROR_OK;
wt_forceZero(flash_data, sizeof(flash_data));
return ret;
}

static int wt_hsm_flash_blank_check(void *context, uint32_t offset,
Expand All @@ -656,7 +659,7 @@ static int wt_hsm_flash_blank_check(void *context, uint32_t offset,
uint8_t flash_data[16];
uint32_t checked = 0u;
uint32_t i;
int ret;
int ret = WH_ERROR_OK;

if (wt_arch_thread_unprivileged()) {
return wt_hsm_flash_gate(context, WT_SPM_KS_FLASH_BLANKCHECK, offset,
Expand All @@ -665,7 +668,7 @@ static int wt_hsm_flash_blank_check(void *context, uint32_t offset,
if (!wt_flash_range_ok(geom, offset, size)) {
return WH_ERROR_BADARGS;
}
while (checked < size) {
while (checked < size && ret == WH_ERROR_OK) {
uint32_t chunk = size - checked;

if (chunk > sizeof(flash_data)) {
Expand All @@ -674,17 +677,17 @@ static int wt_hsm_flash_blank_check(void *context, uint32_t offset,
ret = wt_flash_read_checked(
(const uint8_t *)(geom->base + offset + checked), flash_data,
chunk);
if (ret != WH_ERROR_OK) {
return ret;
}
for (i = 0u; i < chunk; i++) {
for (i = 0u; i < chunk && ret == WH_ERROR_OK; i++) {
if (flash_data[i] != 0xFFu) {
return WH_ERROR_NOTBLANK;
ret = WH_ERROR_NOTBLANK;
}
}
checked += chunk;
if (ret == WH_ERROR_OK) {
checked += chunk;
}
}
return WH_ERROR_OK;
wt_forceZero(flash_data, sizeof(flash_data));
return ret;
}

const whFlashCb g_wt_hsm_flash_cb = {
Expand Down Expand Up @@ -719,8 +722,8 @@ int wt_hsm_flash_format(void)
}

/* SERVICE_FWU staging into the wolfBoot update partition (WT-FWU-0002). The
* privileged FWU coroutine erases each target sector lazily, programs the
* candidate, and verifies every block against the memory-mapped secure flash.
* unprivileged FWU SP crosses the privileged SVC gate to erase each target
* sector lazily, program the candidate, and verify each block in secure flash.
* install() arms wolfBoot's real WRITEONCE update trigger in the UPDATE
* partition trailer (wt_fwu_wolfboot_arm_trailer), so the next boot swaps the
* staged image; the swapped image is still gated by authenticated launch and
Expand Down
Loading
Loading